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
Related
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 have a Primefaces commandLink which I have used it many times in my application. Now I want to store it's URL in a bundle.property file to make it maintainable. which xhtml attribute should I use to redirect it?
I already tried things like:
actionListener="#{bundle.Myurl}"
action="#{bundle.Myurl}"
target="#{bundle.Myurl}"
Myurl also contains this: sales/index.xhtml
but none of them run as I want!
You shouldn't use command links for page-to-page navigation in first place. Use a normal link.
If you have an internal URL / (implicit) navigation outcome:
<h:link value="link" outcome="#{bundle.Myurl}" />
Or if you have an external URL:
<h:outputLink value="#{bundle.Myurl}">link</h:outputLink>
Your attempts failed because the actionListener and action attributes are declared as MethodExpression attributes, meaning that any EL will be interpreted as a bean action method. The target attribute has an entirely different meaning, which is exactly the same as the generated HTML <a> element has.
See also:
When should I use h:outputLink instead of h:commandLink?
When i use
<h:button>
or
<h:link>
i can't make any business action in managed bean ?
Do I have to use
<h:form>
and
<h:commandButton>
or
<h:commandLink>
with action param or there is another solution ?
Depends on the kind of request you'd like to fire.
If it needs to be a non-idempotent POST request, just use <h:form> with <h:commandXxx action>. Again depending on the concrete functional requirement, you can render the results conditionally in the same view, or send a redirect to the target view afterwards.
If it needs to be an idempotent GET request, use <h:link>/<h:button> and perform the action in #PostConstruct method in the request/view scoped backing bean associated with the target page. If you need to pass parameters, use <f:param> to set them on <h:link>/<h:button> and use <f:viewParam> and <f:event type="preRenderView"> in target view to set and process them in backing bean associated with target view.
All in all, just use the right tool for the job as specified by concrete functional requirement (which you unfortunately didn't tell anything about in your question).
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Communication in JSF 2.0
No, you can't do that with h:link or h:button, there are meant to be bookmarkable GET urls. So if you want to perform business action, you need to use either commandButton or commandLink. Note that it's also worth to use h:outputLink for generating bookmarkable links between pages because is much more SEO friendly.
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.
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.