We are using JSF-2.1.7 and in all our form post requests. I am trying to justify whether to use <h:commandButton> or <h:commandLink> . The appearance of <h:commandLink> (href <a/> ) can be controlled using style and jQuery.
Which is recommended <h:commandButton> or <h:commandLink>? Is there any real advantage?
There is no functional difference apart from the generated markup and the appearance. The <h:commandButton> generates a HTML <input type="submit"> element and the <h:commandLink> generates a HTML <a> element which uses JavaScript to submit the form. Both are to be used to submit a form. Additional styling is irrelevant to the functionality.
Use the <h:commandButton> if you need a submit button and use the <h:commandLink> if you need a submit link. If that doesn't make sense to you, then I don't know. If you can't decide which one to use, just choose the one which makes the most sense in UI perspective. Ask the web designer if you're unsure.
The difference between <h:commandLink> and <h:outputLink> is by the way more interesting. This is been answered in detail here: When should I use h:outputLink instead of h:commandLink?
For a form, I prefer the h:commandbutton
h:commandbutton is like a button in HTML where you can set the action of a backing bean.
h:commandlink is like a link in HTML (the tag a) where you also can set the action of a backing bean
To use the css style in JSF, you can use the attribute 'styleClass'.
In short, my recommendation is a mix of <h:commandButton type="submit"> for the primary (default) submit button and <h:commandLink>s for any additional buttons (e.g. filter, sort, lookup, preview, generate password, ...).
Lengthy explanation follows:
First, some background: One should probably also be aware of the different <h:commandButton> type attributes. (The type attribute translates directly to the generated <input type=""> attribute.) I haven't found this explicitly stated anywhere, but some tests showed that:
type="submit" (defaults to this if omitted) does the normal "submit" behaviour of the form (i.e. POSTing the form) as well as the action and/or actionListener.
type="reset" does the normal "reset" behaviour (i.e. clearing/resetting the form fields) without calling any action and/or actionListeners.
type="button" generates a button (apparently <input type="button"> is a bit more limited than the <button> tag) without calling any action and/or actionListeners.
Apart from resetting the fields, the latter two seem to be useful only to activate e.g. Javascript. They don't POST the form.
So to answer the question: in a form context:
<h:commandButton> (which is equivalent to <h:commandButton type="submit">, remember) is often the most useful, especially as most browsers now implement activation of the first submit button found in the DOM tree of the form when Enter is pressed. This might improve your form's user experience
E.g. it is somewhat faster to log with:
Username Tab Password Enter
as opposed to
Username Tab Password ... move hand from keyboard to mouse, hunt pointer and position on button, click.
Also keep in mind that any <input> buttons (optionally CSS-styled) can still be reached via keyboard by Tabing until the <a> (CSS-styled as a button) has focus, and then Spacebar.
However, for additional buttons on the form that should do some other action instead of submitting (or "just" clearing the fields), <h:commandLink> would be more appropriate. This can still be reached via keyboard by Tabing until the <a> (CSS-styled as a button) has focus, and then Enter. Note that this is inconsistent with buttons generated with <h:commandButton>, which may be CSS-styled to look identical, but are handled differently by the browser (Tab...Spacebar).
That is the general explanation, BUT there are some issues you might want to take note of...
When you do not have a <h:commandButton type="submit"> button on a form, only a <h:commandLink> button (or even no buttons at all), when the user presses Enter the form is still submitted, but without the benefit of a action{Listener} running. Which might not be too big a problem, as the form values get stored in the backing bean and shown again when the page loads, so apart from the server roundtrip the user will often not notice anything is amiss. But that might not be how you want Enter to be handled.... The only way I can think of at the moment circumventing that, is to put an onSubmit event on the form which activates your default <h:commandLink> button via Javascript.... Arghhhh!!
You should also make sure that your CSS style selectors are sound.
A.mystyle is applied to <h:commandLink>;
INPUT[type=submit].mystyle to <h:commandButton type="submit">;
INPUT[type=reset].mystyle to <h:commandButton type="reset">;
INPUT[type=button].mystyle to <h:commandButton type="button">;
These can of course be concatenated with a comma as the selector for a single style definition. Or if you want to take the risk of something else being styled as a mystyle button, you could omit the A/INPUT specifiers. However, I have styled my buttons as above, so that I could also use this:
SPAN.mystyle definition for when the link or button is disabled (e.g. via the disabled attribute) - this allows you to supply a toned-down (greyed) look for a disabled button.
I have also run into some height differences (line height on Button vs. content height on Link - which may be a problem if your button includes a background image as icon instead of text), and also some slight differences in how :before/:after pseudoclasses are handled. All I'm saying: test and retest your CSS on both <h:commandButton>s and <h:commandLink>s to make sure they look (essentially) the same!
Here is my summary cheat sheet:
JSF <h:commandButton <h:commandButton <h:commandButton <h:commandLink>
type="submit"> type="reset"> type="button">
Translates to <input <input <input <a>
type="submit"> type="reset"> type="button">
Submit form POST no, clears flds no POST
Javascript events YES YES YES YES
action{Listener} YES no no YES
Enter on form activates YES no no no
Tab...+Enter activates YES(*) YES YES YES
Tab...+Space activates YES(*) YES YES no
Highlight on Tab-focus:
- Firefox 32 YES no no no
- Chrome 41 YES YES YES YES
- Internet Explorer 11 YES YES YES YES
- Opera 28 YES YES YES no(*)
(*=Opera 28 seems not to allow tabbing (or Alt+Arrow) to hyperlinks to activate them.)
Correct me if I'm wrong but the first difference between these two is the fact, that <h:commandButton> doesn't need JavaScript to be enabled in a browser. If your webpage is JS heavy then you can use <h:commandLink>, otherwise it might be better to keep it JS free in case your user wants to use sth like Tor Browser and you are ok with it.
The second one is how these two will behave in a webpage. The <h:commandLink> will just do what it is supposed to do or sometimes also fire a method from backing bean that has #PostConstruct annotation.
While <h:commandButton> may also fire inline JavaScripts which may lead to firing other methods from backing bean. However it will also automatically refresh the view.
Related
I have a JSF/PrimeFaces form page set up to edit some configuration details. At the bottom are Submit and Cancel buttons implemented as CommandButton. The Cancel button looks like this:
<p:commandButton
action="priorPage.xhtml?faces-redirect=true"
value="Cancel" />
The problem is that the view bean still winds up doing more processing on the data that's been entered into the form than I'd like. It isn't updating anything in the database, but if (say) I enter a string into a field that's looking for a numeric in the bean, it still produces errors.
Part of my solution is, of course, to get the bean to gracefully handle that sort of bad data, and I'm working on it. But I'd also like to tweak that button so that it just takes the user to the prior page. Is there some attribute I can set that will prevent the form from being processed at all?
The <p:commandButton> submits the form. You don't want to submit the form. You should then not use the <p:commandButton>, but just <p:button>.
<p:button value="Cancel" outcome="priorPage.xhtml" />
See also:
Difference between h:button and h:commandButton
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
}
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
I'm trying to render a button that should be initially rendered disabled and at some point enabled by client side actions. I'm using the component from a4j with the following code:
<a4j:commandButton id="myButton" disabled="true" onclick="myFunction()">
The problem is when the disabled attribute is set to true, the events are not attached to the component, resulting in this html code:
<input type="button" onclick="return false" ... />
So when I try to enable via javascript, the button is enabled, but the buttons don't have the event listeners attached.
So far, the only two solutions I can think about are:
Assigning the value of the disabled attribute to a bean property and rerender the button.
Render initially enabled and disabled on the load page through javascript
Both options would work but they are not very clean, I don't want to make a petition to the server every time I enable the button.
That's just how stateful component based MVC frameworks like JSF works. As part of safeguard against tampered/hacked requests, the framework re-evaluates the disabled (and rendered) attribute of an input element whenever it's about to apply the request values. Otherwise endusers would be able to invoke actions or submit values they're not allowed to do by server side restrictions which would potentially put doors wide open to attacks.
The two solutions which you mentioned are perfectly fine. I'd opt for the first one if you don't want to allow the enduser to tamper/hack it. It can easily be done by ajax.
I am trying to popup a window when someone clicks a button on the data table.
<h:commandButton
action="#{cacheController.popupDetails}"
immediate="false"
onclick="popup()"
value="View Details"
styleClass="submit">
</h:commandButton>
The associated popup function is
function popup() {
window.open('RDDetails.jsf','popupWindow', 'dependent=yes, menubar=no, toolbar=no, height=500, width=400');
}
Now in the new 'RDDetails.jsf" file, I am trying to access the same managedBean cacheController. But the problem is, the pop-up window and JSF lifecycle is not in sync. As a result, the popup first displays blank and when I refresh, it pulls out the proper data.
Is there anyway I can click on a button which will do some processing in the managed bean and then opens a pop up which rerieves the processed data from the managed bean.
I am using JSF 1.1.
You're here basically firing two independent requests: one associated with the form submit and other which opens the RDDetails.jsf in a popup. You'll need to combine this in one request. You can achieve this in basically two ways:
Get rid of the onclick and just add target="_blank" to the <h:form> so that it get submitted into a new window/tab.
Block the default action by adding return false; to the onclick and do the business logic in the constructor of the bean associated with RDDetails.jsf. The only (major) caveat is here that the model won't be updated with the form fields. Thus, you'll need to pass the form fields as request parameters of the popup URL manually with help of JavaScript. You can then make use of managed property entries in the faces-config.xml to inject the GET request parameters into the model.
First way is obviously the easiest, but this doesn't give you a "fullworthy" popup/modal dialog. The second way is a bit harder (unless you've already a good grasp on both JavaScript and JSF). I would then consider to look for a component library which provides a ready-to-use popup component.
See my example:
<h:commandLink action="#{controller.myAction}" onmousedown="document.forms['idform'].target='_blank';">
I'm using jsf 1.1