How to navigate with request parameters? - jsf-2

I want to navigate from one page to another page, say from page1 with bean1 to page2 with bean2. I need to pass some parameters from bean1 to bean2.
I would like to understand how to use #ManagedProperty for parameters and <f:viewParam> in <f:metadata> portion of page2. Say, I have field1, field2 and field3 available in bean1 and bean2 with getters and setters. My understanding is that I will have to define view params in Metadata of page2:
Like
<f:metadata>
<f:viewParam name="field1" value="#{bean2.field1}"/>
<f:viewParam name="field2" value="#{bean2.field2}"/>
<f:viewParam name="field3" value="#{bean2.field3}"/>
</f:metadata>
I am not sure where I use annotations for #ManagedProperty to define the parameters field1, field2 and field3, in bean1 or bean2.
On page1 I can use "page2?faces-redirect=true&includeViewParams=true"
Can I use the same in one of my methods instead in page1, say on response to a submit of commandlink?
If I need to have those three fields in both page1 and page2, can I define those hidden fields?

You need to specify them as <f:param> in the <h:link> of page1.xhtml.
<h:link value="Go to page2" outcome="page2">
<f:param name="field1" value="#{bean1.field1}" />
<f:param name="field2" value="#{bean1.field2}" />
<f:param name="field3" value="#{bean1.field3}" />
</h:link>
You can then use <f:viewParam> (or #ManagedProperty, but this allows less fine grained validation) to set them in bean of page2.xhtml.
<f:metadata>
<f:viewParam name="field1" value="#{bean2.field1}" />
<f:viewParam name="field2" value="#{bean2.field2}" />
<f:viewParam name="field3" value="#{bean2.field3}" />
</f:metadata>
You do not need to send a POST request by <h:commandLink> with faces-redirect and includeViewParam here. Just a simple GET request by <h:link> is much simpler and SEO friendlier.
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
ViewParam vs #ManagedProperty(value = "#{param.id}")
When should I use h:outputLink instead of h:commandLink?
Communication in JSF 2.0 - Processing GET request parameters

Related

How to pass a variable on p:commandButton ajax request

I have a problem in handling a query string variable. I have a variable edit, that I append in the query string. By default it's true, meaning my page would be in edit mode, if false then the page would be in view mode. So in the page I read and assign the value of the edit query string variable to my backing bean:
#Named
#RequestScoped
public class UserAction {
private boolean edit;
//setter, getter
}
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="edit" value="#{userAction.edit}" />
</f:metadata>
</ui:define>
Which works fine on first load of the page. For example edit=true, my page renders all the input components, but when I hit the clear button:
<p:commandButton value="Reset" process="#this" update="#form" action="#{userAction.clear()}">
<f:actionListener
type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" />
<f:param name="edit" value="true"></f:param>
</p:commandButton>
The form re-renders without the input components because edit parameter is now false.
I tried, replacing RequestScoped with ViewScoped, but it seems that f:viewParam is not working for some reason.
I also tried setPropertyActionListener, the edit setter is called but when the getter is called the value reverts back to false.
I know that it is a scope problem because I don't encounter the same error with almost the same code but with ConversationScoped. But I just need this backing bean to be RequestScope.
Any idea?

Configuration of the beans when using <f:param> <f:viewParam>

I'm trying to pass a parameter between a JSF page to another, from a bean to another. I know it is a common question, infact I've tried several approaches before writing it down.
To do that I have put both the beans in session scope and added in the first bean the following:
<p:commandButton value="Submit" type="submit"
actionListener="#{sourceBean.save}" action="success">
<f:setPropertyActionListener
target="#{targetBean.foo}" value="#{sourceBean.foo}" />
</p:commandButton>
The problem is that I don't want these beans to be in session scope but in view scope.
So I tried to put in my first page:
<p:commandButton value="Submit" type="submit"
actionListener="#{sourceBean.save}" action="success">
<f:param name="foo" value="#{sourceBean.foo}"/>
</p:commandButton>
And in the second page:
<f:metadata>
<f:viewParam id="foo" name="foo" value="#{targetBean.foo}"
/>
</f:metadata>
The problem is that the passed String is null so, obviously, I get an error form the Converter.
I think I'm missing something in the configuration of my managed beans. Do I have to link target and source bean in someway?
At this moment I have this configuration:
<managed-bean>
<managed-bean-name>targetBean</managed-bean-name>
<managed-bean-class>guiBeans.TargetBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>sourceBean</managed-bean-name>
<managed-bean-class>guiBeans.SourceBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
Another question: In my app, the value foo.id, that I use during the conversion, is set autonatically by the database when I save the object so when I call:
actionListener="#{sourceBean.save}"
The converter gets the id and turns it into a String (and viceversa, if needed).
So, I wanted to know if in JSF is first called the actionListener or the function that sets the parameters .
Could be this the reason why I get a null String? Thanks a lot.
The <f:param> is evaluated during rendering of the form, not during submitting of the form. Your problem suggests that the #{sourceBean.foo} value is only been set during submitting the form and thus not available during rendering of the form.
You'd basically need to replace action="success" by action="#{bean.action}" with
public String action() {
return "success?foo=" + foo.getId();
}
Or, if you're using navigation cases
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/some.xhtml</to-view-id>
<redirect>
<view-param>
<name>foo</name>
<value>#{sourceBean.foo.id}</value>
</view-param>
</redirect>
</navigation-case>
Unrelated to the concrete problem, the <f:param> doesn't support the converter attribute at all. You'd have to access the desired property directly (which is id in the above example).

Create composite component for f:metadata

I want to create a composite component which adds some common meta data to views, like:
<viewController:metadata controller="orderController"/>
the component:
<composite:interface>
<composite:attribute name="controller" />
</composite:interface>
<composite:implementation>
<f:metadata>
<f:viewParam name="id" value="#{cc.attrs.controller.id}" />
<f:event type="preRenderView"
listener="#{cc.attrs.controller.initConversation}" />
</f:metadata>
</composite:implementation>
i do similar things to add a button bar to all views and it works fine, but it seems its not possible with f:metadata.
Am i right or is there something wrong with my code?
thanks
This isn't possible. The <f:metadata> has to go in the view associated with the view ID. See also the tag documentation (emphasis mine):
Declare the metadata facet for this view. This must be a child of the <f:view>. This tag must reside within the top level XHTML file for the given viewId, or in a template client, but not in a template. The implementation must insure that the direct child of the facet is a UIPanel, even if there is only one child of the facet. The implementation must set the id of the UIPanel to be the value of the UIViewRoot.METADATA_FACET_NAME symbolic constant.

How to edit data in Primefaces DataTable without in-cell editing?

I have 2 pages.
Add Page for add a new item
List Page for show all items
When I click on Edit icon on List Page, I want to show selected data on Add Page for editing and update its data if I click on save button. How to do this?
Pass the row identifier as a parameter to the button. For example, assuming that #{item} is the currently iterated item and has some Long id property which uniquely identifies the item.
<p:button icon="ui-icon-pencil" outcome="edit.xhtml">
<f:param name="id" value="#{item.id}" />
</p:button>
In the target page, edit.xhtml, you can use <f:viewParam> to convert, validate and set it as a bean property.
<f:metadata>
<f:viewParam name="id" value="#{bean.item}" required="true" converter="itemConverter" />
</f:metadata>
...
<p:inputText value="#{bean.item.name}" />
<p:inputText value="#{bean.item.shortName}" />
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Communication in JSF 2.0 - Processing GET request parameters

Passing view parameter through backing bean

I have an inputtext in a page page1.xhtml and I want to pass the value the user will enter into a second page page2.xhmtl as a view parameter using a get method. I use an h:button and put as outcome value from the backing bean but it when I navigate to the second page I the parameter is not passed. What's wrong? Is the value not passed to the backing bean before pressing the button and therefore value cannot be read? Is there another way to do it?
page1.xhtml
h:inputText id="q" value="#{QBean.q}"></h:inputText>
<h:button value="Done" outcome="page2?q=#{indexBean.q}">
page2.xhtml
<f:metadata>
<f:viewParam name="q" value="#{QBean.q}"/>
</f:metadata>
QBean
private String q;
//setter
//getter
Your sole functional requirement seems to be that you want a GET form instead of a POST form. In that case, use normal HTML elements, not JSF components.
<form action="page2.xhtml">
<input name="q" />
<input type="submit" value="Done" />
</form>
You could use the POST-REDIRECT-GET approach and take commandButton instead: <h:commandButton value="Done" action="page2?faces-redirect=true&includeViewParams=true"/>

Resources