JSF best practices : One form for the whole application or a few smaller forrms? - jsf

What is the best practice in JSF , to create one main <h:form> in template for example and put all content inside or to have a few forms for each parts, for example if we have two logical blocks of code on the page we should have wrapped these blocks in 2 separate forms ???

This is an overly broad question, and it as well has nothing to di with JSF. It is a question of HTML understanding and design.
If you abstract away all of the JSF details, you'll find out that the rendered component is a plain HTML <form>. To recall the specification, a form is:
a section of a document containing normal content, markup, special elements called controls (checkboxes, radio buttons, menus, etc.), and labels on those controls. Users generally "complete" a form by modifying its controls (entering text, selecting menu items, etc.), before submitting the form to an agent for processing (e.g., to a Web server, to a mail server, etc.)
So ultimately a whole form will be submitted to the server. In case of a component-based framework, like JSF, the bound values of components will populate the backing beans with the submitted data, in case there are no errors.
But what data will be submitted? All data that is within a form. So, if you have one global form that means that all unrelated pieces of information will be collected: like user credentials, product choices, selection of preferences, etc. And it will be done all at once. Most probably it won't yield the desired functionality, but will produce unexpected results.
The problem there was mixing of concerns: one form contained non-related data that was not designed to be submitted together. This leaves us with a one-form-per-user-interaction, like one form for user authentication/logout, another form for storing user preferences, yet another one for keeping product choices, etc. One global form also is likely to leave you with nesting forms problem, taking you some time to figure it out.
Regarding the choice of where to put that form, it is as well depending on the logical separation: if you have user login/logout on every page it could be placed in master template. Per-view forms are likely to be put in template client. Moreover, you'll find it convenient to sometimes put them side-by-side to distinguish the functionality.
Also, form may alter the expected behaviour. One final example: user choice of products. Consider two cases.
The first one:
<h:form>
<ui:repeat value="#{bean.purchasedProducts}" var="product">
<h:outputText value=#{product.name}/>
<h:inputText value=#{product.quantity}/>
<h:commandButton value="Change"/>
</h:dataTable>
</h:form>
The second one:
<ui:repeat value="#{bean.purchasedProducts}" var="product">
<h:form>
<h:outputText value=#{product.name}/>
<h:inputText value=#{product.quantity}/>
<h:commandButton value="Change"/>
</h:form>
</h:dataTable>
While the first example will update all products, the second one will update only the relevant product.
Finally, there is no 'best practice' or 'universal solution'. I think that it's best to depart from separation of concerns when designing an HTML document.
And, yes, I'm voting to close the question.

Related

How to stop action delete when reload page in jsf [duplicate]

We're using JSF 2.0 on WebSphere v8.5 with several component libraries PrimeFaces 4.0, Tomahawk 2.0, RichFaces, etc.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed, or when the submit button is clicked once again. I have many applications with different scenarios.
For now I have considered disabling the button with a piece of JavaScript in onclick attribute, but this is not satisfying. I'm looking for a pure Java implementation for this purpose, something like the Struts2 <s:token>.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed
For that there are at least 2 solutions which can not be combined:
Perform a redirect after synchronous post. This way the refresh would only re-execute the redirected GET request instead of the initial request. Disadvantage: you can't make use of the request scope anymore to provide any feedback to the enduser. JSF 2.0 has solved this by offering the new flash scope. See also How to show faces message in the redirected page.
Perform the POST asynchronously in the background (using ajax). This way the refresh would only re-execute the initial GET request which opened the form. You only need to make sure that those forms are initially opened by a GET request only, i.e. you should never perform page-to-page navigation by POST (which is at its own already a bad design anyway). See also When should I use h:outputLink instead of h:commandLink?
or when the submit button is clicked once again
For that there are basically also at least 2 solutions, which could if necessary be combined:
Just block the enduser from being able to press the submit button during the submit and/or after successful submit. There are various ways for this, all depending on the concrete functional and design requirements. You can use JavaScript to disable the button during submit. You can use JSF's disabled or rendered attributes to disable or hide the button after submit. See also How to do double-click prevention in JSF 2. You can also use an overlay window during processing ajax requests to block any enduser interaction. PrimeFaces has <p:blockUI> for the purpose.
Validate uniqueness of the newly added entity in the server side. This is way much more robust if you absolutely want to avoid duplication for technical reasons rather than for functional reasons. It's fairly simple: put a UNIQUE constraint on the DB column in question. If this constraint is violated, then the DB (and DB interaction framework like JPA) will throw a constraint violation exception. This is best to be done in combination with a custom JSF validator which validates the input beforehand by performing a SELECT on exactly that column and checking if no record is returned. A JSF validator allows you to display the problem in flavor of a friendly faces message. See also among others Validate email format and uniqueness against DB.
Instead of creating a token manually, you can use BalusC' solution. He proposed a Post-Redirect-GET pattern in his blog
Alternative solutions can be found in these answers:
Simple flow management in Post-Redirect-Get pattern
How can Flash scope help in implementing the PostRedirectGet (PRG) pattern in JSF2.0
<!--Tag to show message given by bean class -->
<p:growl id="messages" />
<h:form>
<h:inputText a:placeholder="Enter Parent Organization Id" id="parent_org_id" value="#{orgMaster.parentOrganization}" requiredMessage="Parent org-id is required" />
<h:commandButton style="margin-bottom:8px;margin-top:5px;" class="btn btn-success btn-block " value="Save" type="submit" action="#{orgMaster.save}" onclick="resetform()" />
</h:form>
public String save() {
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getFlash().setKeepMessages(true); //This keeps the message even on reloading of page
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Your submission is successful.", " ")); // To show the message on clicking of submit button
return "organizationMaster?faces-redirect=true"; // to reload the page with resetting of all fields of the form.. here my page name is organizationMaster...you can write the name of form whose firlds you want to reset on submission
}

JSF: Custom component in tables not rendered as expected

Is there a suitable solution for the custom component root-issue in the meanwhile?
In short terms, the problem is that using custom components containing of both a label and an input field within a table like
<h:panelGrid columns="2">
<jl:inputField value="#{testBean.value1}"/>
<jl:inputField value="#{testBean.value2}"/>
</h:panelGrid>
... will be rendered within a single row.
A dirty solution would be to place the panelGrid within the component which will cause a rendering of a separate table for each input field. This is most likely the case cause there isn't a bottom-up but a top-down approach when parsing the code.
Do you have any other ideas how to handle this? Custom tags were mentioned in the discussion.

Render a jsf element on mouseover

I have a <h:panelGrid> and a h:commandLink(link is basically a image).Now I want that on mouseover event , Then link should be render(render='true') and on mouseout event, it gets removed render='false'.But I am unable to create the logic that How can I do this with these events as the approach I am using is To set the values of bean true and false on this event.
Here is my code
<h:form>
<h:panelGrid mouseover='** we cannot call a bean method here which changes the bean value **'>
This is the Div On which I want to apply mouseover event
</h:panelGrid>
<h:commandLink id="btn" render={renderBean.renderLink}>
<h:graphicImage url="image.jpg"/>
</h:commandLink>
</h:form>
The default value of renderLink attribute of renderBean is false. Now I want to know the way that How can I change its value to true on mouseover event? Is it possible? OR Anyother solution in JSF w.r.t this requirement
You have to remember in JSF that the page will first be processed server-side by the JSF engine in the web server. At that time all JSF tags will be converted into their HTML equivalent. The render attribute tells the server-side engine whether or not to output an HTML a (anchor) link in the place of the <h:commandLink> element.
The behavior you're looking for, namely responding to mouse events, is client-side functionality. It happens in the browser, not at the web server, so no JSF is involved. The solution is to handle the mouse events in JavaScript, not JSF. You will typically set (or remove) the CSS attribute display:none on the id called btn (unfortunately it's slightly more complex as JSF will mangle the element id a bit). There are lots of posts here on StackOverflow that deal with how to handle client-side events in JavaScript. Using jQuery for example is a really common approach.
I recommend to get started you take a look at the blog of one of our best JSF resources and long-time StackOverflow user BalusC: http://balusc.blogspot.com.
There's a lot to learn and you'll get a good start by going there first (and searching for his posts on SO).
Good luck.

Why was "immediate" attribute added to the EditableValueHolders?

Initially immediate flag was only intended for ActionSource interface. But later on it was added to the EditableValueHolder interface also. What was the reason for design decision ?
It's to be used to prioritize validation on several EditableValueHolder components in the same form.
Imagine a form containing input components with immediate="true" as well as input components without this attribute. The immediate inputs will be validated during apply request values phase (which is one phase earlier than usual). The non-immediate inputs will be validated during validations phase (which is the usual phase). If validation fails for at least one of the immediate inputs, then the non-immediate inputs won't be converted/validated at all and thus won't generate any conversion/validation error messages. This is particularly useful in forms with complex validation rules where it doesn't make sense to validate component Y when validation for (immediate) component X has failed anyway.
When used in combination with immediate="true" on a command button in the same form, this will cause all non-immediate inputs being completely skipped. A good real world example is a login form with 2 fields "username" and "password" with required="true" and 2 buttons: "login" and "password forgotten". You could put immediate="true" on the "username" field and the "password forgotten" button to skip the required="true" check on the password field.
In the dark JSF 1.x ages, the immediate="true" was also often (ab)used as a hack in combination with valueChangeListener and FacesContext#renderResponse(), more than often in cascading dropdown lists. Long story short, here's an old blog article on that. To the point, it enables developers to execute a backing bean method on change of a <h:selectOneMenu> without that all other inputs in the same form are been validated. But these days, with the ajax awesomeness, this hack is unnecessary. You can find a concretre example of this case at the bottom of our <h:selectOneMenu> wiki page.
These days, the immediate="true" is still often (ab)used in order to have a specific button which completely bypasses all other inputs, such as a logout button in a "God-form" antipattern (whereby everything is been thrown together in a huge <h:form>), or a cancel button which incorrectly submits the form. Such a button would break when you start to actually need the immediate="true" the right way on one of the inputs. You'd better put such a logout button in its own form, or to change it to process only itself (process="#this" in PrimeFaces). And you'd better change such a cancel button to just refresh the page synchronously by <h:button value="Cancel" />. This works fine if the form is tied to a request/view scoped bean and browser caching is disabled on dynamic pages.
See also:
Should immediate="true" never be used when dealing with an AJAXified JSF 2.0 component?
Trying to understand immediate="true" skipping inputs when it shouldn't

Conditional string concatenation/building in JSF

I'm trying to convert a JSP Page to JSF (no JSP code allowed), but have stumbled upon an issue.
Note: This is academic, so no "dirty" solution will do.
I have jsp code that sets the image source and alt text of an image depending on various conditions. There are concatenations and switch conditions. This is inside a loop.
Now, I can reproduce the loop that goes through all the values, like this:
<ui:repeat value="#{gameapi.game.fieldsList}" var="field">
<h:graphicImage id="field#{field.fieldNr}" styleClass="field#{field.fieldNr}"
url="..." alt="" title=""/>
</ui:repeat>
However, there's a total of over 20 combinations for the image url and alt text. Obviously, I doubt writing a conditionally rendered or chosen graphicImage Tag for every possibility is an elegant solution, since this would only get uglier with every additional combination.
I also cannot create those strings in the underlying java code, since that would violate the idea of separating view, model and controller.
So what is the best solution to do this? It seems like a huge weakness of JSF.
Consider using a variation on the MVVM pattern. You can have managed beans that are dedicated to view logic separate from the business logic managed beans.
<ui:repeat value="#{bizBean.list}" var="_row">
<h:graphicImage
url="#{viewModelBean.images[_row.outcome]}"
alt="#{viewModelBean.alts[_row.outcome]}"
title="#{viewModelBean.titles[_row.outcome]}" />
</ui:repeat>
viewModelBean could be an application-scoped type with a bunch of map properties. This assumes a relatively simple case, but the pattern is suited to more sophisticated requirements.
Note: the repeating control should be a NamingContainer, so trying to set the client identifier in the VDL is redundant. See here for more.

Resources