How to forward using h:commandButton - jsf

I have a view where I have a form with p:commandButton and everything works fine beacuse I'm using forward and that's what I need:
<h:form id="formularioAltas">
// More code
<p:commandButton value="Guardar" action="#{altasBean.agregarRefaccion()}" update="cboAlmacen cboEstado cboCategoria" />
</h:form>
The method agregarRefaccion() is void so does not changes the page, I think a forward takes place after that action because it always has the same url. That is Ok beacuse that is what I need.
In the same view a have another form where I have a problem with h:commandButton.
<h:form id="myForm" enctype="multipart/form-data" prependId="false">
// More code
<h:commandButton id="button" style="background-color: black; color: aliceblue" value="Guardar imagen para #{altasBean.refaccion.idRefaccion}" action="#{altasBean.subirImagen()}" />
</h:form>
The subirImagen() method is void too so I thought a forward would take place after that action... but it doesn't. The page updates and the url changes so that means a redirect did that.
I will always need a forward. No matter if it is a p:commandButton or a h:commandButton.
I think has something to be with PrimeFaces and the differences of p:commandButton with JSF h:commandButton.
So I need a forward in that h:commandButton.
Edit
I always have an url like this blabla/AlmacenGM/
but when h:commandButton goes the url is: blabla/AlmacenGM/faces/altas.xhtml
The url changes. I have tried to return the string "altas" int the method subirImagen() so a forward should take place but it still changing the url.
Any ideas?

There's no forward with p:commandButton. It's actually an ajax request what you're peforming, because it's its default behaviour.
However, the standard JSF h:commandButton performs a forward request, as long as you return a String with the navigation case in your action method. If you see a redirection taking place there, you must be forcing it in your bean side.
See also:
Ajax update and submission using h:commandButton

Related

How to redirect to a page after printing with primefaces Printer?

I have used the primefaces printer and wanted to redirect to previous page after printing.I used Printer like this:
<p:commandButton value="Print" type="button" title="Print" actionListener="#{currentpage.redirect}">
<f:ajax execute="#this"/>
<p:printer target="printer" />
</p:commandButton>
In redirect method of currentpage bean i deleted the record which works fine but if i try to redirect it to previous page it doesn't do anything.
public void redirect(ActionEvent actionevent) {
/* Deleted the record */
}
Please guide me if i can do this way or anyother way.
Thanks in advance.
There are several misconceptions in your code:
actionListener method can not fire a redirect. That could be done in action
An ajax request cannot fire a redirect. Ajax is meant to work as an asynchronous request to the server and get the desired result to the current view and handle the response to update the view without refreshing the page nor without navigating.
If using Primefaces components, you should work with them for efficiency in your page. For example, <p:commandButton> should work with <p:ajax> rather than <f:ajax>. But in this case, <p:commandButton> already has ajax capabilities built-in, so there's no need to use any of these ajax components.
After knowing this, you know that your design should change to this:
<p:commandButton value="Print" type="button" title="Print"
action="#{currentpage.redirect}" process="#this">
<p:printer target="printer" />
</p:commandButton>
And the method declaration to:
//parameterless
public void redirect() {
/* Deleted the record */
}
PrimeFaces let's you add behavior when the ajax request is complete by usage of oncomplete attribute. This attribute receives the name of a javascript function that will be invoked right when the ajax request finishes without problems. In this method, you can add the logic for your redirection:
<p:commandButton value="Print" type="button" title="Print"
action="#{currentpage.redirect}" process="#this" oncomplete="redirect()">
<p:printer target="printer" />
</p:commandButton>
<script type="text/javascript>
redirect = function() {
window.location.href = '<desired url>';
}
</script>

commandButton inactive after ajax rendering

I have a problem with these two commandButton : Join and Leave.
I want to hide Join if I click on leave and vice-versa.
When I put ajax on false, there is no problem (but all the page is refresh and I don't find this optimal).
But when ajax attribut is on true with specific updating (cf comment in the code), the rendering is good but the new button whitch appear become inactive. If I click on it, nothing happens (well it's seems the actionListener trigger but the view is not refreshed, I have to manual refresh to see the difference)
Thanks for reading.
<h:form id="formWaitingList" rendered="#{connexion.connected}" >
<p:commandButton id="Join"
actionListener = "#{connexion.joinWaitingList()}"
rendered="#{!connexion.waiting}"
ajax="false"
<!-- ajax="true"
update="Join,Leave"-->
value="Join"/>
<p:commandButton id="Leave"
value="Leave"
ajax="false"
<!-- ajax="true"
udpate="Join,Leave"-->
rendered="#{connexion.waiting}"
actionListener ="#{connexion.leaveWaitingList()}" />
</h:form>
It seems that you're not entirely familiar with HTML/JavaScript. You know, JSF is basically a HTML/JavaScript(/CSS) code generator. Ajax updating works basically like this in JavaScript:
After sending the ajax request to JSF via XMLHttpRequest, retrieve a XML response which contains all elements which needs to be updated along with their client IDs.
For every to-be-updated element, use document.getElementById(clientId) to find it in the current HTML DOM tree.
Replace that element by new element as specified in ajax XML response.
However, if a JSF component has not generated its HTML representation because of rendered="false", then there's nothing in the HTML DOM tree which can be found and replaced. That totally explains the symptoms you're "seeing".
You basically need to wrap conditionally rendered JSF components in a component whose HTML representation is always rendered and then reference it instead in the ajax update.
For example,
<h:form>
...
<h:panelGroup id="buttons">
<p:commandButton ... update="buttons" rendered="#{condition}" />
<p:commandButton ... update="buttons" rendered="#{not condition}" />
</h:panelGroup>
</h:form>
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

Difference between h:button and h:commandButton

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.

jsf richfaces a4j:jsFunction forward outcome

Is it possible to create a4j:jsFunction that will call a method inside my managed bean and from there to perform forward to another jsf page ?
Thank's In Advance.
No, it's not possible because the <a4j:jsFunction> will create a javascript method available in the HTML that communicates with the server via Ajax. Instead, you could do something ugly like this:
<h:form id="myForm">
<a4j:jsFunction name="myJSFunction" action="#{myBean.jsLogic}"
oncomplete="document.getElementById('myForm:btnForward').click();" />
<a4j:commandButton id="btnForward" style="display: none;"
action="#{myBean.doForward}" />
</h:form>
In this case at the end of your js function, you will call the method of a <a4j:commandButton> (also <a4j:commandLink> or any other h component) that could do the navigation.
Well, it is not really a forward but you can do a redirect:
Just be sure that your corresponding navigation-case in faces-config file has the corresponding tag:
<redirect />
Then after the ajax call the browser will be redirected to the specified page.
This has the disadvantage in respect to Luiggi's response that makes two server calls, the ajax one and then the redirection.
As advantage, it makes cleaner code.

Issue with primefaces , Specially p:commandButton

I developed a JSF 2 application using RichFaces first and then migrated to Primefaces recently.
All things are working fine except:
When clicking on a button and calling update="id1, id2, etc", it does not update my page contents.
<p:commandButton value="Logout" action="#{profile.logout}" /> does not work, in logout method I simply clear session and return to login page, but it stays on the same page.
I am using Tomcat 6.0.32 on Windows 7 with 4GB RAM. I m using PrimeFaces 2.2, the latest Stable build.
When clicking on a button and calling update="id1, id2, etc", it does not update my page contents.
You have to provide more context before we can give an answer on that. My first guesses would be that you have to remove those commas (and only separate by spaces like in standard JSF2 and RF4). My second guess would be that those components are simply not resolveable in the current component and NamingContainer hierarchy. My third guess would be that the ajax request didn't return a valid ajax response (use Firebug to check it).
<p:commandButton value="Logout" action="#{profile.logout}" /> does not work, in logout method I simply clear session and return to login page, but it stays on the same page.
The <p:commandButton> sends by default an ajax request. If you want to navigate to a different view as response on an ajax request, then you have to send a redirect. You can do this among others by adding the faces-redirect=true parameter to the outcome:
return "login?faces-redirect=true";
Or, alternatively, just turn off ajax on the button:
<p:commandButton ... ajax="false" />
Or, use the standard <h:commandButton> instead:
<h:commandButton ... />

Resources