In JSF 2, what is the difference between h:button and h:commandButton ?
<h:button>
The <h:button> generates a HTML <input type="button">. The generated element uses JavaScript to navigate to the page given by the attribute outcome, using a HTTP GET request.
E.g.
<h:button value="GET button" outcome="otherpage" />
will generate
<input type="button" onclick="window.location.href='/contextpath/otherpage.xhtml'; return false;" value="GET button" />
Even though this ends up in a (bookmarkable) URL change in the browser address bar, this is not SEO-friendly. Searchbots won't follow the URL in the onclick. You'd better use a <h:outputLink> or <h:link> if SEO is important on the given URL. You could if necessary throw in some CSS on the generated HTML <a> element to make it to look like a button.
Do note that while you can put an EL expression referring a method in outcome attribute as below,
<h:button value="GET button" outcome="#{bean.getOutcome()}" />
it will not be invoked when you click the button. Instead, it is already invoked when the page containing the button is rendered for the sole purpose to obtain the navigation outcome to be embedded in the generated onclick code. If you ever attempted to use the action method syntax as in outcome="#{bean.action}", you would already be hinted by this mistake/misconception by facing a javax.el.ELException: Could not find property actionMethod in class com.example.Bean.
If you intend to invoke a method as result of a POST request, use <h:commandButton> instead, see below. Or if you intend to invoke a method as result of a GET request, head to Invoke JSF managed bean action on page load or if you also have GET request parameters via <f:param>, How do I process GET query string URL parameters in backing bean on page load?
<h:commandButton>
The <h:commandButton> generates a HTML <input type="submit"> button which submits by default the parent <h:form> using HTTP POST method and invokes the actions attached to action, actionListener and/or <f:ajax listener>, if any. The <h:form> is required.
E.g.
<h:form id="form">
<h:commandButton id="button" value="POST button" action="otherpage" />
</h:form>
will generate
<form id="form" name="form" method="post" action="/contextpath/currentpage.xhtml" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="form" value="form" />
<input type="submit" name="form:button" value="POST button" />
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="...." autocomplete="off" />
</form>
Note that it thus submits to the current page (the form action URL will show up in the browser address bar). It will afterwards forward to the target page, without any change in the URL in the browser address bar. You could add ?faces-redirect=true parameter to the outcome value to trigger a redirect after POST (as per the Post-Redirect-Get pattern) so that the target URL becomes bookmarkable.
The <h:commandButton> is usually exclusively used to submit a POST form, not to perform page-to-page navigation. Normally, the action points to some business action, such as saving the form data in DB, which returns a String outcome.
<h:commandButton ... action="#{bean.save}" />
with
public String save() {
// ...
return "otherpage";
}
Returning null or void will bring you back to the same view. Returning an empty string also, but it would recreate any view scoped bean. These days, with modern JSF2 and <f:ajax>, more than often actions just return to the same view (thus, null or void) wherein the results are conditionally rendered by ajax.
public void save() {
// ...
}
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
When should I use h:outputLink instead of h:commandLink?
Differences between action and actionListener
h:button - clicking on a h:button issues a bookmarkable GET request.
h:commandbutton - Instead of a get request, h:commandbutton issues a POST request which sends the form data back to the server.
h:commandButton must be enclosed in a h:form and has the two ways of navigation i.e. static by setting the action attribute and dynamic by setting the actionListener attribute hence it is more advanced as follows:
<h:form>
<h:commandButton action="page.xhtml" value="cmdButton"/>
</h:form>
this code generates the follwing html:
<form id="j_idt7" name="j_idt7" method="post" action="/jsf/faces/index.xhtml" enctype="application/x-www-form-urlencoded">
whereas the h:button is simpler and just used for static or rule based navigation as follows
<h:button outcome="page.xhtml" value="button"/>
the generated html is
<title>Facelet Title</title></head><body><input type="button" onclick="window.location.href='/jsf/faces/page.xhtml'; return false;" value="button" />
This is taken from the book - The Complete Reference by Ed Burns & Chris Schalk
h:commandButton vs h:button
What’s the difference between h:commandButton|h:commandLink and
h:button|h:link ?
The latter two components were introduced in 2.0 to enable bookmarkable
JSF pages, when used in concert with the View Parameters feature.
There are 3 main differences between h:button|h:link and
h:commandButton|h:commandLink.
First, h:button|h:link causes the browser to issue an HTTP GET
request, while h:commandButton|h:commandLink does a form POST. This
means that any components in the page that have values entered by the
user, such as text fields, checkboxes, etc., will not automatically
be submitted to the server when using h:button|h:link. To cause
values to be submitted with h:button|h:link, extra action has to be
taken, using the “View Parameters” feature.
The second main difference between the two kinds of components is that
h:button|h:link has an outcome attribute to describe where to go next
while h:commandButton|h:commandLink uses an action attribute for this
purpose. This is because the former does not result in an ActionEvent
in the event system, while the latter does.
Finally, and most important to the complete understanding of this
feature, the h:button|h:link components cause the navigation system to
be asked to derive the outcome during the rendering of the page, and
the answer to this question is encoded in the markup of the page. In
contrast, the h:commandButton|h:commandLink components cause the
navigation system to be asked to derive the outcome on the POSTBACK
from the page. This is a difference in timing. Rendering always
happens before POSTBACK.
Here is what the JSF javadocs have to say about the commandButton action attribute:
MethodExpression representing the application action to invoke when
this component is activated by the user. The expression must evaluate
to a public method that takes no parameters, and returns an Object
(the toString() of which is called to derive the logical outcome)
which is passed to the NavigationHandler for this application.
It would be illuminating to me if anyone can explain what that has to do with any of the answers on this page. It seems pretty clear that action refers to some page's filename and not a method.
Related
This question already has an answer here:
How to call JSF backing bean method only when onclick/oncomplete/on... event occurs and not on page load
(1 answer)
Closed 5 years ago.
<h:outputLink value="/4JVA-157292-war/supinfo/auth/mycar.xhtml">Car</h:outputLink>
<h:outputLink value="Log Out" onclick="${loginController.logout()}" />
As you see, If i click the Car link. I will excute the ${loginController.logout()}, but if i delete the Log out. I will go into the car page.
<h:ouputLink> component is used to render plain a anchor element with its href attribute evaluated as value attribute of <h:outputLink> with the query parameters attached in case the component has <f:param> tags as its children.
<h:ouputLink> is not used to execute server-side actions as you wrongly seemed to expect. You may have confused it with a <h:commandLink> component that is used to trigger a server-side action via a JavaScript call.
If you want to call the action method you must switch to a command comnponent (or its derivative) like <h:commandLink>. Its action attribute should point to the desired action method, like so:
<h:commandLink value="Log out" action="#{loginController.logout}" />
In this way you will be able to execute the bean action method.
Also it is worth noting that since JSF 2.0 there has been an <h:link> component that is useful for handling application-wide navigation. It takes a navigation case outcome in its outcome attribute thus leaving <h:outputLink> component useful for links to external resources.
For more information on the subject read the following answer: When should I use h:outputLink instead of h:commandLink?.
As to the cause of the problem you faced, onclick attribute is rendered as onclick event handler of the generated a element that responds to a click event on the HTML element it is attached to. In case the event is fired a client-side JavaScript code is called (by function call onclick points to or by executing inline code that is contained therein). Do note that onclick runs on the client (in JavaScript context within web browser) while action runs on the server (executes Java code depending on the submit button pressed within web server).
Usage of onclick may be fruitful at least in the following circumstances:
in case it is used in conjunction with a command component it may stop form submission to the server if some client-side requirements are not met (i.e. confirm dialog was shown and cancel button was pressed, or client-side validation failed) as soon as the event will be fired before any consecutive events associated with the element (like form submission):
<h:commandLink value="Delete item" action="#{bean.delete(item)}" onclick="return confirm("Are you sure you want to delete this item?");" ... />
or
<h:commandLink value="Submit data" action="#{bean.action}" onclick="return inputValid();" ... />
with
<script type="text/javascript">
function inputValid() {
var isInputValid = ...;
//decide what's valid or not and set variable to true/false accordingly
return isInputValid;
}
</script>
it may be used to trigger some GUI changes, especially when used in conjunction with non-command components, like in:
<h:button value="Show dialog" onclick="showDialog(); return false;" ... />
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.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated - point 2
What is <f:ajax execute="#all"> really supposed to do? It POSTs only the enclosing form
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
<p:commandbutton> action doesn't work inside <p:dialog>
I was confounded by this issue for a while. Instead of a series of independent forms, I converted to a template, that is, rather than making a call to a xhtml with listed forms, usually as ui:include, I make a call to those formerly ui:included xhtml pages that ui:content captured in a parent template.
When should I use an <h:outputLink> instead of an <h:commandLink>?
I understand that a commandLink generates an HTTP post; I'm guessing that outputLink will generate HTTP gets. That said, most of the JSF tutorial material I've read uses commandLink (almost?) exclusively.
Context: I am implementing a wee little demo project that shows a header link to a user page, much like Stack Overflow's...
...and I am not sure if commandLink (perhaps using ?faces-redirect=true for bookmarkability) or outputLink is the right choice.
The <h:outputLink> renders a fullworthy HTML <a> element with the proper URL in the href attribute which fires a bookmarkable GET request. It cannot directly invoke a managed bean action method.
<h:outputLink value="destination.xhtml">link text</h:outputLink>
The <h:commandLink> renders a HTML <a> element with an onclick script which submits a (hidden) POST form and can invoke a managed bean action method. It's also required to be placed inside a <h:form>.
<h:form>
<h:commandLink value="link text" action="destination" />
</h:form>
The ?faces-redirect=true parameter on the <h:commandLink>, which triggers a redirect after the POST (as per the Post-Redirect-Get pattern), only improves bookmarkability of the target page when the link is actually clicked (the URL won't be "one behind" anymore), but it doesn't change the href of the <a> element to be a fullworthy URL. It still remains #.
<h:form>
<h:commandLink value="link text" action="destination?faces-redirect=true" />
</h:form>
Since JSF 2.0, there's also the <h:link> which can take a view ID (a navigation case outcome) instead of an URL. It will generate a HTML <a> element as well with the proper URL in href.
<h:link value="link text" outcome="destination" />
So, if it's for pure and bookmarkable page-to-page navigation like the SO username link, then use <h:outputLink> or <h:link>. That's also better for SEO since bots usually doesn't cipher POST forms nor JS code. Also, UX will be improved as the pages are now bookmarkable and the URL is not "one behind" anymore.
When necessary, you can do the preprocessing job in the constructor or #PostConstruct of a #RequestScoped or #ViewScoped #ManagedBean which is attached to the destination page in question. You can make use of #ManagedProperty or <f:viewParam> to set GET parameters as bean properties.
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Bookmarkability via View Parameters feature
How to navigate in JSF? How to make URL reflect current page (and not previous one)
I also see that the page loading (performance) takes a long time on using h:commandLink than h:link. h:link is faster compared to h:commandLink
I'm trying to create a button that once clicked will change a property in a bean.
<h:commandButton type="button" action="#{loginBean.withdraw}" id="thousand" class="buttons" style="top:180px;left:570px;">
<f:setPropertyActionListener target="#{loginBean.withdrawAmount}" value="1000" />
</h:commandButton>
public class LoginBean {
int withdrawAmount;
This method only works when I omit the type="button" from the commandButton, but with the type="button" it doesn't work and I'm not sure why.
I need the type="button" to be there , is there any way to keep it and still make it work ?
There is an error in your facelet snippet:
There is no such attribute as class for <h:commandButton>. Possibly you meant styleClass.
As for the problem you have, you have to:
Either provide a setter method for the withdrawAmount property
public void setWithdrawAmount(int withdrawAmount) {
this.withdrawAmount = withdrawAmount;
}
and your facelet should look like:
<h:commandButton type="submit"
action="#{loginBean.withdraw}"
id="thousand"
styleClass="buttons"
style="top:180px;left:570px;">
<f:setPropertyActionListener target="#{loginBean.withdrawAmount}"
value="1000" />
</h:commandButton>
Or, you can get rid of the <f:setPropertyActionListener> and add a statement the changes the value of the withdrawAmount as a first line of the #{loginBean.withdraw} method.
In this case your facelet snippet should look like:
<h:commandButton type="submit"
action="#{loginBean.withdraw}"
id="thousand"
styleClass="buttons"
style="top:180px;left:570px;" />
and your LoginBean#withdraw() method should start with the statement, that changes the withdrawAmount value:
public String withdraw() {
this.withdrawAmount = 1000;
//the remaining logic.
}
Personally, I would prefer the first option.
More info:
< h:commandButton > tag reference
JSF Core Tag :setPropertyActionListener vs attribute vs param
The type is the entire reason why you're having this issue. I'm posting this answer because the accepted answer doesn't explain why you're experiencing the issue.
<h:commandButton/> is designed to work in 3 modes:
submit: This is the default mode that the button is set to. This mode sends an HTTP POST request to the server that triggers the JSF request processing lifecycle. It's only this mode that enables you to trigger backing bean methods(using the action or actionListener attributes).
button: This mode triggers a GET request in the application. As GET requests go, this mode is mostly suited for navigation, i.e. requesting another view or page. In this mode, there's no easy/straightforward way to execute backing bean code, or trigger the JSF request processing lifecycle. This is your current issue
reset: This mode simply resets the value of all input components within its enclosing <h:form/>
Reference:
JSF2 Command Button VDL
JSF redirect via commandButton
Difference between h:button and h:commandButton
I'm using JSF 2.0 and I have a problem with navigation after both commandLink and commandButton. I use following code:
<h:commandLink action="login?faces-redirect=true"
value="#{showElementBean.showElement()}"> Login </h:commandLink>
<h:commandButton action="login?faces-redirect=true" value="Move to login.xhtml" />
These tags are inside a form, login is just an example. Result of clicking on rendered controls is always POST with refresh of a current page. What do I wrong?
Edit:
According to comments of BalusC I' adding real code fragment:
<h:commandLink actionListener="#{showElementBean.showElement(element)}"
value="View" > </h:commandLink>
I have a page with a list of elements and I want to add links that leads to element view page. Thus I need to pass this element to a show page. I'm JSF primer, e.g. in Rails I'd use GET and URL params, but I don't know how to do it 'in JSF-way'.
There are a lot of possible causes for this behaviour. They are all cited in the following answer, along with solutions: commandButton/commandLink/ajax action/listener method not invoked or input value not updated.
However, in your particular case, you seem rather to be interested in plain GET requests instead of POST requests, as all you want is simple page-to-page navigation. In that case, you need a <h:link> or <h:button> instead:
<h:link outcome="login" value="Login" />
<h:button outcome="login" value="Move to login.xhtml" />
(I have no idea what you're trying to do with both #{showElementBean.showElement()} and Login as command link value, so I omitted the former)
See also:
When should I use h:outputLink instead of h:commandLink?
Refer this info: JSF HTML Tags
h:commandButton
The commandButton tag renders an HTML submit button that can be
associated with a backing bean or ActionListener class for event
handling purposes. The display value of the button can also be
obtained from a message bundle to support internationalization (I18N).
Example
<h:commandButton id="button1" value="#{bundle.checkoutLabel}" action="#{shoppingCartBean.checkout}" />
HTML Output
<input id="form:button1" name="form:button1" type="submit" value="Check Out" onclick="someEvent();" />
h:commandLink
The commandLink tag renders an HTML anchor tag that behaves like a
form submit button and that can be associated with a backing bean or
ActionListener class for event handling purposes. The display value of
the link can also be obtained from a message bundle to support
internationalization (I18N).
Example
<h:commandLink id="link1" value="#{bundle.checkoutLabel}" action="#{shoppingCartBean.checkout}" />
HTML Output
Check Out
Noticed that backing bean method is not called if the form is for file upload:
<h:form name="searchForm" enctype="multipart/form-data" method="post" action="/search">
I also faced with that issue and adding the
<h:form><h:commandLink></h:commandLink> </h:form>
solved my problem.