How to pass a variable on p:commandButton ajax request - jsf-2

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?

Related

Any way to bypass form validation on p:commandButton without using o:ignoreValidationFailed or immediate=true

I create page forms with a parameter that tells them where to return when done. The backing bean is #ReqeuestScoped and includes this:
<f:metadata>
<f:viewParam name="return" value="#{createGroup.paramReturn}" />
</f:metadata>
The form has fields with validators, so the cancel button has to skip validation. So, the cancel button looks like this:
<p:commandButton value="Cancel"
action="#{createGroup.doCancel}"
immediate="true"
/>
The purpose of the doCancel() method is to go into Flash scope and return the value set with setParamReturn method.
The problem is with the immediate="true" attribute is that the Flash storage that has the paramReturn variable in it is no longer available. If someone could tell me how to fix that this would be my preferred solution.
Of course without the immediate="true" attribute the action is never invoked because the form cannot pass validation. Another solution would be to cause validation to be ignored some other way.
I have looked at the OmniFaces <o:ignoreValidationFailed> tag and it seems to do what I want, but I don't want to import a whole library for just this tag. However, that is what I will do if there is no other simple way to fix this.

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).

Keep get parameters when submitting a form

I'm trying to do something simple in JSF but I can't get it working for some reason.
What I want is to post information with a form from a page reached with a GET parameter and keep this GET parameter whenever I submit the form.
<f:metadata>
<f:viewParam name="someId" value="#{someController.something}" converter="#{someConverter}" />
</f:metadata>
This is the way I choose to bind the GET parameter, this is working fine when I'm doing the GET request.
On the very same page I have a
<h:form>
<!-- (... various input ...) -->
<h:commandLink action="#{someController.create}" value="Create" />
</h:form>
When I submit it, even if data are right, I never get my "something" not to be null.
The use case is easy, I have a one to many relation and I want to access the "one" with the id as a GET parameter and list the "many" on the page and below the listing the form allows me to add a new element in the "many" list.
I'd like to make it work (of course) and be the cleaner possible,
Could someone tell me what's the best way to achieve this?
Thanks!
Either make the SomeController bean #ViewScoped so that the bean lives as long as you're interacting with the same view,
#ManagedBean
#ViewScoped
public class SomeController {
// ...
}
or use <f:param> in UICommand components to pass GET parameters through
<h:commandLink>
<f:param name="someId" value="#{param.someId}" />
</h:commandLink>

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"/>

Understanding navigation in JSF

Trying to build a simple JSF application. One i don't get is, what mechanism is to use to trigger page reload. I have tried following
<h:selectOneMenu
id="ChallengesListBox"
onchange="submit()"
valueChangeListener="#{bean.projectselected}">
<f:selectItems value="#{bean.projectnames}"/>
</h:selectOneMenu>
<h:commandButton value="submit" action="#{bean.submit}" />
with
public String submit() {
this.description.setRendered(true);
return null;
}
But this has no effect. The bean method
public String submit()
remains untouched, as I can see in debug mode.
This is not related to navigation. There are many causes why a bean action method is not invoked. You can find them all in this answer: commandButton/commandLink/ajax action/listener method not invoked or input value not updated
I suspest that you've either simply no <h:form>, or that you have multiple buttons in the form (the first one would then be invoked on submit()), or that the button is by itself not rendered during processing of the form submit.
Unrelated to the concrete problem, this JSF 1.x style approach is very clumsy. As you're apparently already on JSF 2.x, I suggest the following much simpler approach:
<h:selectOneMenu value="#{bean.projectname}">
<f:selectItems value="#{bean.projectnames}" />
<f:ajax render="somepanel" />
</h:selectOneMenu>
<h:panelGroup id="somepanel">
<h:outputText value="#{bean.description}" rendered="#{not empty bean.projectname}" />
</h:panelGroup>
(this will render the #{bean.description} value whenever the #{bean.projectname} is not null/empty according to the selection of the drop down list)
And make sure that you remove all binding attributes to the backing bean. Also make sure that the bean is #ViewScoped whenever you have input/button components inside the <h:panelGroup id="somepanel">.

Resources