I am using the Facelet Templating Technology to layout my page in a JSF 2 app that I am working on.
In my header.xhtml, primefaces requires that menubar be enclosed in h:form.
<h:form>
<p:menubar autoSubmenuDisplay="true">
Menu Items here!
</p:menubar>
</h:form>
So, in my contents pages, I will have another h:form or more.
Will it just work if I just place the h:form in my template.xhtml?
<h:body>
<h:form>
<div id="top">
<ui:insert name="header"><ui:include src="sections/header.xhtml"/></ui:insert>
</div>
<div>
<div id="left">
<ui:insert name="sidebar"><ui:include src="sections/sidebar.xhtml"/></ui:insert>
</div>
<div id="content" class="left_content">
<ui:insert name="content">Content</ui:insert>
</div>
</div>
<div id="bottom">
<ui:insert name="footer"><ui:include src="sections/footer.xhtml"/></ui:insert>
</div>
<h:form>
</h:body>
I am actually thinking of a use case where I need multiple h:form in a page.
Thanks
You can safely use multiple forms in a JSF page. It's not different than when using plain HTML.
Nesting <form>
elements is invalid in HTML. Since JSF just generates a bunch of HTML, it's not different in JSF. Nesting <h:form>
is therefore also invalid in JSF.
<h:form>
...
<h:form> <!-- This is INVALID! -->
...
</h:form>
...
</h:form>
The browser behavior as to submitting a nested form is unspecified. It may or may not work the way you expect. It may for instance just refresh the page without invoking the bean action method. Even if you move the nested form (or a component that contains it) outside of the parent form with dom manipulation (or by e.g. using the PrimeFaces appendTo="@(body)"
), it still won't work and there should be no nested forms at time of loading the page.
As to which forms you need to keep, having a single "god" <h:form>
is actually a poor practice. So, you'd best remove the outer <h:form>
from the master template and let the header
, sidebar
, content
etc sections each define its own <h:form>
. Multiple parallel forms is valid.
<h:form>
...
</h:form>
<h:form> <!-- This is valid. -->
...
</h:form>
Each form must have one clear responsibility. E.g. a login form, a search form, the main form, the dialog form, etc. You don't want to unnecessarily process all other forms/inputs, when you submit a certain form.
Note thus that when you submit a certain form, other forms are NOT processed. So, if you intend to process an input of another form anyway, then you've a design problem. Either put it in the same form or throw in some ugly JavaScript hacks to copy the needed information into a hidden field of the form containing the submit button.
Within a certain form, you can however use ajax to limit the processing of the inputs to a smaller subset. E.g. <f:ajax execute="@this">
will process (submit/convert/validate/invoke) only the current component and not others within the same form. This is usually to be used in use cases wherein other inputs within the same form need to be dynamically filled/rendered/toggled, e.g. dependent dropdown menus, autocomplete lists, selection tables, etc.