Good morning in my timezone,
I am adding some features in a JSF application,
i add the following code
<h:link outcome="nameOut1.innerName" >
<f:param name="idX" value="#{xbean.idElement}"/>
<f:param name="idY" value="#{xBean.param1.param2.id}"/>
</h:link>
And i change it by this one
<h:commandLink action="#{xBean.validateBeforeClose}" >
<f:param name="idX" value="#{xbean.idElement}"/>
<f:param name="idY" value="#{xBean.param1.param2.id}"/>
</h:commandLink>
And in the bean
public String validateBeforeClose(){
if (isValidToRemove()) {
setValidationToRemove(true);
return "";
}else{
return "nameOut1.innerName";
}
}
if the first condition is true then it come back to the same View, and displays a popupWindow, if this condition is not met , then return the same outcome that the old link tag was setting.
The problem is : True the link the h:link tag the parameters are sent, i see that in the URL, but through the action the parameters are not sent.
in the faces-config i have the following configuration
<navigation-case>
<from-outcome>nameOut1.innerName</from-outcome>
<to-view-id>/folder1/folder2/view2.xhtml</to-view-id>
<redirect include-view-params="true">
</redirect>
</navigation-case>
Why is this happening ?
Thanks in advance
Best regards
Related
I use a commandLink to navigate to another page:
<t:commandLink action="go_orderForm" immediate="true">
<h:outputText value="#{order.number}" />
<t:updateActionListener property="#{orderForm.orderId}"
value="#{order.id}" />
</t:commandLink>
This is working and setting the value of order.id to the backing bean orderForm.orderId.
In another place, I use a commandButton to call an action in the backing bean of the current page and navigate after to the new page:
<h:commandButton value="Create Batch" action="#{orderList.createBatchOrder}" />
The action in the backing bean looks like:
public String createBatchOrder() {
// do something
return "go_orderForm";
}
The faces-config.xml contains
<navigation-rule>
<navigation-case>
<from-outcome>go_orderForm</from-outcome>
<to-view-id>/orderForm.jsp</to-view-id>
</navigation-case>
</navigation-rule>
How can I pass the parameter for orderForm.orderId when I navigate using the action in the backing bean?
Before redirect put your parameter to flash:
FacesContext.getCurrentInstance().getExternalContext().getFlash().put(key, value);
After redirect you may get it by:
FacesContext.getCurrentInstance().getExternalContext().getFlash().get(key);
i have a very simple code here:
<a4j:commandLink action="#{ticketAboxEventHelper.removeAboxTicket(ticketAbox)}"
onclick="if(!confirm('Are you sure ... ?')) return false;"
reRender="aboxlistpanel">
<h:graphicImage alt="Delete" url="../../img/dialog-error-5.png" title="Delete" />
<a4j:support event="oncomplete"
action="#{editTicketNewAction.testRerender()}"
reRender="aboxlistpanel"
/>
</a4j:commandLink>
When the link clicked the system must
ask if the user is confirmed
do the action
rerender the aboxlistpanel
Now my problem is the rerendering is hapenning before the action is getting finished. any idea how it can be done in the right way?
Your action methods is not valid for JSF 1.2 and you don't need the <a4j:support>. Since you want to pass a parameter, you should use <f:attribute /> and actionListener :
<a4j:commandLink actionListener="#{ticketAboxEventHelper.removeAboxTicket}" onclick="if(!confirm('Are you sure ... ?')) return false;" reRender="aboxlistpanel">
<h:graphicImage alt="Delete" url="../../img/dialog-error-5.png" title="Delete" />
<f:attribute name="ticket" value="#{ticketAbox}" />
</a4j:commandLink>
Your bean method will look like this :
public void removeAboxTicket(ActionEvent event)
{
TicketAbox ticket = (TicketAbox)event.getComponent().getAttributes().get("ticket");
// Your business logic
}
More info :
How to pass parameters in method expression JSF 2.0
Solved. I wrapped the offending JSF code in a and everything began working as expected. related to answer <a4j:commandLink> Not Rerendering. i solved it first and then found out someone else solved it in the same way. hmmm....
I'm trying to get na few parameters (now it's two, but on the other xhtml probably I'll need more).
On page index.html I have a link, to page Threads.xhtml, with parameters user_id and section_id:
<h:dataTable value="#{Sections.sections}" var="Section">
<h:column>
<h:form>
<h:link value="#{Section.section_label}" outcome="Threads">
<f:param name="user_id" value="#{LoginIn.user_id}"/>
<f:param name="section_id" value="#{Section.section_id}"/>
</h:link>
</h:form>
</h:column>
</h:dataTable>
When I click into on of the links, it goes to for ex.:
Project/faces/Threads.xhtml?user_id=5§ion_id=2
So it's good :).
Now, on page Threads.xhtml I have a link (one link, not dataTable, as on index.xhtml - to create new section), to page NewThread.xhtml, with parameters user_id and section_id:
<h:form>
<h:link value="#{msg.create_new_thread}" outcome="NewThread">
<f:param name="user_id" value="#{param.user_id}"/>
<f:param name="section_id" value="#{param.section_id}"/>
</h:link>
</h:form>
When I click into on of the links, it goes to, for ex..:
Project/faces/NewThread.xhtml?user_id=5§ion_id=2
So it's also nice :).
Now, I check on NewThread.xhtml page values of user_id and section_id, by:
<h:outputText value="User_id: #{param.user_id}"/><br/>
<h:outputText value="Section_id: #{param.section_id}"/><br/>
And I see on page values:
User_id: 5
Section_id: 2
So ok :). But now, when I'm trying to get these values in Java code NewThread.java, they returns only null:
FacesContext facesContext = FacesContext.getCurrentInstance();
String user_id = (String) facesContext.getExternalContext().getRequestParameterMap().get("user_id");
String section_id= (String) facesContext.getExternalContext().getRequestParameterMap().get("section_id");
//For test:
System.out.println("User_id: " + user_id);
System.out.println("Section_id: " + section_id);
And in console i've got:
User_id: null
Section_id: null
I've also try toString() method, but it didn't help.
Going back to the index.xhtml, when I click on the link to one of the section, ex. second section (by any user, ex. user_id=5), it goes to Threads.xhtml:
Project/faces/Threads.xhtml?user_id=5§ion_id=2
And on Threads.xhtml I've got list of Threads of second section (but this part of xhtml code is irrelevant):
<h:dataTable value="#{Threads.threads}" var="Thread">
<h:column>
<h:link value="#{Thread.thread_label}" outcome="Threads">
<f:param name="thread_id" value="#{Thread.thread_id}"/>
</h:link>
</h:column>
</h:dataTable>
And on Java code of Threads.java, I've got:
FacesContext facesContext = FacesContext.getCurrentInstance();
String section_id = (String) facesContext.getExternalContext().getRequestParameterMap().get("section_id");
System.out.println("Section_id: " + section_id);
And in console i've got:
Section_id: 2
So WTF? Once it works, but another time it won't.
EDIT:
Sorry, I forgot. I access into NewThread.java, by commandButton in NewThread.xhtml:
<h:commandButton value="#{msg.add_thread}" action="#{NewThread.AddThread}"/>
and it calls AddThread method in NewThread.java; and in try (of try-catch) of AddThread method, there I'm trying to get parameters.
I've also already add into faces-config.xml:
<managed-bean>
<managed-bean-name>Threads</managed-bean-name>
<managed-bean-class>forum.Threads</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>NewThread</managed-bean-name>
<managed-bean-class>forum.NewThread</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
When you click an h:commandButton, a new request is made. The problem is that the parameters are not being passed to this request.
So, if you want your request scoped bean NewThread to get the data from the request parameters, you have to include the parameters in the request made from the h:commandButton too. Try this:
<h:commandButton value="#{msg.add_thread}" action="#{NewThread.AddThread}">
<f:param name="user_id" value="#{param.user_id}"/>
<f:param name="section_id" value="#{param.section_id}"/>
</h:commandButton>
As you are using JSF 2, you may find useful to use f:metadata with f:viewParam together with the includeViewParameters=true trick for navigating between pages, check out these questions:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Handling view parameters in JSF after post
As elias says, when you click on the command button there's a new request (a post) and this won't include the get parameters from the previous request.
An alternative solution is using the mentioned view parameters in combination with the o:form component from OmniFaces, that has an attribute that automatically retains all view parameters as GET parameters:
<o:form includeViewParams="true">
This has the additional advantage that users keep to see those parameters in the URL, so if they copy it or refresh the page by hitting enter in the address bar of their browser, things keep working as expected.
I am looking for a another way of JSF navigation other than mentioning navigation-cases in faces-config.xml.
At present i am using faces-config.xml to navigate. I want to clean it up.
Please suggest all other ways so that i can use whatever suits my need.
For simple page-to-page navigation (without submitting anything) you should be using <h:outputLink> instead of <h:commandLink>.
So, instead of
<h:form>
<h:commandLink value="Page 1" action="page1" />
<h:commandLink value="Page 2" action="page2" />
<h:commandLink value="Page 3" action="page3" />
</h:form>
and those navigation cases
<navigation-rule>
<navigation-case>
<from-outcome>page1</from-outcome>
<to-view-id>page1.jsf</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>page2</from-outcome>
<to-view-id>page2.jsf</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>page3</from-outcome>
<to-view-id>page3.jsf</to-view-id>
</navigation-case>
</navigation-rule>
you should use
<h:outputLink value="page1.jsf">Page 1</h:outputLink>
<h:outputLink value="page2.jsf">Page 2</h:outputLink>
<h:outputLink value="page3.jsf">Page 3</h:outputLink>
For real form submits you should rewrite the action methods to return void or null instead of an outcome. So, instead of
<h:form>
<h:inputText value="#{bean.query}" />
<h:commandButton value="Search" action="#{bean.search}" />
</h:form>
with
public String search() {
results = searchService.find(query);
return "results";
}
on one page and
<h:dataTable value="#{bean.results}" var="result">
...
</h:dataTable>
on other page and this navigation case
<navigation-rule>
<from-view-id>search.jsf</from-view-id>
<navigation-case>
<from-outcome>results</from-outcome>
<to-view-id>results.jsf</to-view-id>
</navigation-case>
</navigation-rule>
you should use
<h:form rendered="#{empty bean.results}">
<h:inputText value="#{bean.query}" />
<h:commandButton value="Search" action="#{bean.search}" />
</h:form>
<h:dataTable value="#{bean.results}" var="result" rendered="#{not empty bean.results}">
...
</h:dataTable>
with
public void search() {
results = searchService.find(query);
}
You can if necessary include page fragments by <jsp:include>.
See also:
When should I use h:outputLink instead of h:commandLink?
//JSF
<h:outputLink value="login.xhtml" >
Login page
</h:outputLink>
//HTML output
<a href="login.xhtml">
Login page
</a>
Refer this URL for more info:-
commandLink and outputLink example
You can set the return value of a navigation action to the name of the page you want to go to (e.g. return "page2"; to switch to page2.jsf). But as far as I know, this feature has been implemented first in JSF 2.0.
From an action in my bean, I'm trying to redirect to another page expecting a view parameter. What is the recommended way to do this in JSF2?
E.g., say my source page is:
http://localhost/page1.xhtml
it has a commandButton that calls an action:
<h:commandButton value="submit" action="#{myBean.submit}" />
where my bean looks like:
#ManagedBean
#RequestScoped
public class MyBean {
private int id;
public String submit() {
//Does stuff
id = setID();
return "success";
}
And now, I want the 'submit' action's return to navigate to
http://localhost/page2.xhtml?id=2
I've tried to do this with a view-param in my navigation case, but with odd results. The faces-config snippet looks like the following:
<navigation-rule>
<from-view-id>/page1.xhtml</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/page2.xhtml</to-view-id>
<redirect>
<view-param>
<name>id</name>
<value>#{myBean.id}</value>
</view-param>
</redirect>
</navigation-case>
</navigation-rule>
The weird behaviour being, even though myBean is set to request scoped, it only calls myBean.getId() the first time I load my application, and reuses that same value for all subsequent calls, producing incorrect view parameters for page2.
So I'm looking for either a better way to do this, or a reason/solution for why the view-param is not being requested from my bean each time.
The unintuitive thing about passing parameters in JSF is that you do not decide what to send (in the action), but rather what you wish to receive (in the target page).
When you do an action that ends with a redirect, the target page metadata is loaded and all required parameters are read and appended to the url as params.
Note that this is exactly the same mechanism as with any other JSF binding: you cannot read inputText's value from one place and have it write somewhere else. The value expression defined in viewParam is used both for reading (before the redirect) and for writing (after the redirect).
With your bean you just do:
#ManagedBean
#RequestScoped
public class MyBean {
private int id;
public String submit() {
//Does stuff
id = setID();
return "success?faces-redirect=true&includeViewParams=true";
}
// setter and getter for id
If the receiving side has:
<f:metadata>
<f:viewParam name="id" value="#{myBean.id}" />
</f:metadata>
It will do exactly what you want.
Without a nicer solution, what I found to work is simply building my query string in the bean return:
public String submit() {
// Do something
return "/page2.xhtml?faces-redirect=true&id=" + id;
}
Not the most flexible of solutions, but seems to work how I want it to.
Also using this approach to clean up the process of building the query string:
http://www.warski.org/blog/?p=185
Check out these:
http://andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/#get
http://mkblog.exadel.com/2010/07/learning-jsf2-page-params-and-page-actions/
You're gonna need something like:
<h:link outcome="success">
<f:param name="foo" value="bar"/>
</h:link>
...and...
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}"/>
</f:metadata>
Judging from this page, something like this might be easier:
<managed-bean>
<managed-bean-name>blog</managed-bean-name>
<managed-bean-class>com.acme.Blog</managed-bean-class>
<managed-property>
<property-name>entryId</property-name>
<value>#{param['id']}</value>
</managed-property>
</managed-bean>
You can do it using Primefaces like this :
<p:button
outcome="/page2.xhtml?faces-redirect=true&id=#{myBean.id}">
</p:button>
Just add the seen attribute to redirect tag as below:
<redirect include-view-params="true">
<view-param>
<name>id</name>
<value>#{myBean.id}</value>
</view-param>
</redirect>
A solution without reference to a Bean:
<h:button value="login"
outcome="content/configuration.xhtml?i=1" />
In my project I needed this approach:
<h:commandButton value="login"
action="content/configuration.xhtml?faces-redirect=true&i=1" />