JSF Ajax method does not persist variable in bean - ajax

I have two forms: one to define some filter settings (ajax) and with sumbit buttons which reloads the page by action="null" and one form with a single command button which executes the ajax listener "#{bean.activate}":
<h:form id="settingsForm">
<h:selectBooleanCheckbox value="#{bean.boolean1}" id="bool1">
<f:ajax event="click" render="#all" execute="bool1"/>
</h:selectBooleanCheckbox>
<ui:repeat var="step" value="#{bean.availableSteps}">
<h:commandLink action="#{bean.navigate(step)}">
<h:outputText value="#{step.name}" />
</h:commandLink>
</ui:repeat>
</h:form>
<h:form id="activateForm">
<h:commandButton value="set activate bool and rerender" >
<f:ajax event="click" execute="#form" render="#all" listener="#{bean.activate}"/>
</h:commandButton>
</h:form>
The problem is following:
when I change the checkbox (boolean in backing bean) and click the submit button in the same form, only the changes (in the backing bean) are persisted which were set in the same form.
When I execute the second form (bean.activate), it rerenders fine (shows some more information), but when I THEN submit the first form, the changes of the second form are lost (but they are working on the same bean). I want that it remembers also the variables set in the second form...
It seems that the values set by the other form are not persisted, because when i perform a form submit, all the "information" stored by ajax of the second form is lost.
e.g.
boolean boolean1 = false; //set by form 1
boolean show = false; //set by form 2 (ajax)
public void activate(Ajaxbehaviour...){ show = true; }
Should there be by default only ONE form at all? it seems that two forms (one big and one just so set a variable by ajax) are too much...

Related

How can I check if multiple checkboxes are checked with JSF / AjaxBehaviorEvent

I have multiple checkboxes - they are given the same id, "choosen" in the xhtml view code.
I have added an Ajax event listener for them, like so:
<ui:repeat var="posts"
value="#{postBacking.postsOverview.posts}">
<h:selectBooleanCheckbox id="choosen"
styleClass="check-margin"
value="#{posts.choosen}" rendered="#{posts.declined =='No'}">
<f:ajax listener="#{postsBacking.isPostsChosen}" event="click" render="#form" execute="#form"/>
</h:selectBooleanCheckbox>
</ui:repeat>
In the listener method in my backingBean, I would like to check if any of these checkboxes are checked, and then set a button disabled if no checkboxes are marked - and enabled if one or more is set.
But how do I get hold of the values of all checkboxes - can I use the AjaxBehaviorEvent objet for that or is there some other way?
While processing the ajax event listener, the checkbox values should normally have been applied to your data model where you can look up the state of user choice. Depending on that state, simply toggle a boolean bean property which disables the command button:
#Named
#ViewScoped
public class MyBean implements Serializable {
private List<Post> posts;
private boolean buttonDisabled = true;
public void ajaxEventListener(BehaviorEvent e) {
boolean anythingChosen = false;
for (Post post : posts) {
if (post.isChosen() && "No".equals(post.getDeclined())) {
anythingChosen = true;
break;
}
}
// or alternatively using the stream api:
// anythingChosen = posts.stream().filter(Post::isChosen).map(Post::getDeclined)
// .anyMatch("No"::equals);
setButtonDisabled(!anythingChosen);
}
// getters, setters ...
}
Using the following form, the command button is disabled as long as no checkbox is checked:
<h:form>
<ui:repeat var="post" value="#{myBean.posts}">
<h:selectBooleanCheckbox value="#{post.chosen}">
<f:ajax event="click" listener="#{myBean.ajaxEventListener}" render="#form" execute="#form"/>
</h:selectBooleanCheckbox>
</ui:repeat>
<h:commandButton action="#{myBean.doSomething()}" value="doSomething"
disabled="#{myBean.buttonDisabled}" />
</h:form>
You can use valueChangeListener rather than using listener and event attributes. The valueChangeListener will be triggered every time you check/uncheck the checkbox.
To get hold of the values when thevalueChangeListener is invoked, you can loop through the postBacking.postsOverview.posts to see if any value is checked.
Don't forget to update the button on <f:ajax render="#form btnId"/> to enable/ disable it.

What URL should I use in $.ajax() in order to submit a form

Working in JSF2 and ajax, i can't figure out what's the value of the $.ajax URL attribute in JSF context as i want to submit a form and update a div staying in the same page
Is it the following?
((HttpServletRequest) facesContext.getExternalContext().getRequest()).getContextPath()`
in my opinion you need pass value to the backing bean and set the parameter, after this you need to update this part (div).
see this http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/
<p:commandButton action="#{bean.setId}" update="div">
<f:attribute name="id" value="12" />
</p:commandButton>
Another way is using flash, see this: https://javaserverfaces.java.net/nonav/docs/2.0/javadocs/javax/faces/context/Flash.html
lets say you have a form like this:
<div id="yourDivId">
<h:outputText value='#{yourControllerClass.yourAttribute}'></h:outputText>
</div>
<h:form>
<h:commandButton value="update">
<f:ajax execute="#form" listener="#{yourControllerClass.updateAttribute}"
render=":yourDiveId">
</f:ajax>
</h:commandButton>
</h:form>
in your ControllerClass/bean:
public final void updateAttribute(AjaxBehaviorEvent event){
// do what ever you want, get values, set another values, after that your Div will be auto updated
}
this way, you don't need to care about ajax params or URL...etc.
EDIT:
if you want to get a paramater from a request URL, then you can get it like this:
String paramVal = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);

Submitted form values not updated in model when adding <f:ajax> to <h:commandButton>

I'm learning how to use ajax within jsf, I made a page that does actually nothing, an input text that is filled with a number, submitted to the server, call the setter for that element with the value submitted, and display the getter's value.
Here's the simple bean's code:
#ManagedBean(name="helper",eager=true)
public class HealthPlanHelper {
String random = "1";
public void setRandomize(String s){
random = s;
System.out.println("Calling setter");
}
public String getRandomize(){
return random;
}
}
And the jsf page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head></h:head>
<h:body>
<h:form>
<h:commandButton action="nothing">
<f:ajax render="num"/>
</h:commandButton>
<h:inputText value="#{helper.randomize}" id="num"/>
</h:form>
</h:body>
</html>
As you see, this is a request scoped bean, whenever I click the button the server shows that it creates an instance of the bean, but the setter method is never called, thus, the getter return always "1" as the value of the string.
When I remove the the setter is called normally.
The <f:ajax> processes by default only the current component (read description of execute attribute). Basically, your code is exactly the same as this:
<h:form>
<h:commandButton action="nothing">
<f:ajax execute="#this" render="num"/>
</h:commandButton>
<h:inputText value="#{helper.randomize}" id="num"/>
</h:form>
In effects, only the <h:commandButton action> is been processed and the <h:inputText value> (and any other input field, if any) is completely ignored.
You need to change the execute attribute to explicitly specify components or sections you'd like to process during the ajax request. Usually, in order to process the entire form, #form is been used:
<h:form>
<h:commandButton action="nothing">
<f:ajax execute="#form" render="num"/>
</h:commandButton>
<h:inputText value="#{helper.randomize}" id="num"/>
</h:form>
See also:
Communication in JSF 2.0 - Ajax (asynchronous) POST form
commandButton/commandLink/ajax action/listener method not invoked or input value not updated (point 8)
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

JSF AJAX validation: execute="#this" render="#form" inconsistent depending on prior requests

I have an h:commandLink that calls a method that changes a property bound to a radio input.
I also have a text input on the same form with some validation (required=true).
If I leave the text input blank, and click on h:commandLink with execute="#this, the radio button updates from the model property as expected, because the text input is never processed and validation never fires.
However, if first I click on a different h:commandLink with execute="#form", then the link with execute="#this", the validation messages go away but the radio button value does not update from the model even though the UIInput for the radio button was never in an invalid state.
I'm finding it annoying that the execute="#this" behaves differently depending on what I had done previously, when my intent with #this was to force everything to update from the model and ignore any submitted values from the components.
I suspect what's happening is something like this:
with #form, radio button and text are both processed.
Radio button is valid so localValue is set
Process validations phase fails overall because of invalid text input, so localValue remains set and does not get cleared or propagate to value
the only way out of this is to explicitly call resetValue() or to re-process the component in question (e.g., execute="#this radio") to clear out localValue and then allow refreshing from bean.
My questions are:
is my understanding of the lifecycle correct?
Am I doing something wrong, or is this one of the annoying-by design things about JSF?
It feels like this may just be another example of this question
How can I populate a text field using PrimeFaces AJAX after validation errors occur?
Unfortunately I feel like I'm finding lots of those lately. :-(
Code example below:
<h:form>
<h:messages/>
Radio =
<h:selectOneRadio value="#{testBean.radioValue}" id="radio" binding="#{radio}">
<f:selectItem itemValue="foo" itemLabel="Foo"/>
<f:selectItem itemValue="bar" itemLabel="Bar"/>
</h:selectOneRadio>
<br></br>
radio bean value = <h:outputText value="#{testBean.radioValue}"/>
<br></br>
radio UIInput localValue = <h:outputText value="#{radio.localValue}"/>
<br></br>
radio UIInput value = <h:outputText value="#{radio.value}"/>
<br></br>
String w/validation = <h:inputText value="#{testBean.stringValue}" required="true" />
<br></br>
<ul>
<li>
<h:commandLink actionListener="#{testBean.changeRadioValue}" value="execute = #form">
<f:ajax render="#form" execute="#form"/>
</h:commandLink>
</li>
<li>
<h:commandLink actionListener="#{testBean.changeRadioValue}" value="execute = #this">
<f:ajax render="#form" execute="#this"/>
</h:commandLink>
</li>
<li>
<h:commandLink actionListener="#{testBean.changeRadioValue}" value="execute = #this radio">
<f:ajax render="#form" execute="#this radio"/>
</h:commandLink>
</li>
</ul>
</h:form>
And this bean:
#ManagedBean
#ViewScoped
public class TestBean {
private String radioValue = "foo";
private String stringValue;
public void changeRadioValue() {
radioValue = "bar";
}
// + getters/setters
}
is my understanding of the lifecycle correct?
Yes.
Am I doing something wrong, or is this one of the annoying-by design things about JSF?
It's one of the "annoying by-design things" of JSF. As stated in my answer on that related question:
Coming back to the concrete problem, I'd imagine that this is an oversight in the JSF2 specification. It would make much more sense to us, JSF developers, when the JSF specification mandates the following:
When JSF needs to update/re-render an input component by an ajax request, and that input component is not included in the process/execute of the ajax request, then JSF should reset the input component's value.
I only don't remember anymore if I have ever reported this against JSF spec. Edit: I reported it: JSF spec issue 1060.

How to call several methods with JSF <f:ajax listener?

Good Afternoon,
I have a search page that uses ajax to render a several datatables without refreshing the page.
It is mandatory for me to call a Method as a Listener for each table.
Below is the snippet for the first datatable that works fine.
To render a second datatable I need to call a method #{evalController.prepareList} as a Listener for the ajax. The problem is that <f:ajax "Listener" attribute won't take more than one method.
So the remaining way is to call <f:ajax several times, and each time with a different listener, which does not work. Is there a way to achieve this?
If not, should I create a method in the managed Bean that calls all the methods that I need and use it as the one listener?
Thanks in advance for your help.
<h:form id="searchform">
<h:panelGrid columns="3" >
<p:inputText value="#{ddnController.patientID}" id="pidinput" maxlength="7" size="7">
<f:ajax execute="#this" event="keyup" render="searchbutton ddntable" listener="#{ddnController.prepareList}"/>
</p:inputText>
<h:commandButton image="#{resource['images/search.png']}" id="searchbutton" value="#{bundle.Search}"
action="submit" actionListener="#{ddnController.prepareList}"
disabled="#{empty ddnController.patientID or ddnController.patientID.equals('0')}"/>
<p:panel><h:outputText value="Saisir 0 pour avoir tous les Patients" style="font-style: italic;"/></p:panel>
</h:panelGrid>
<p:dataTable id="ddntable" value="#{ddnController.items}" var="ddn" rendered="#{!empty ddnController.items}" paginator="true" >....
I am still not sure why the composite method do not have effect when called. Probably it is not called during before or after the right phase (I'll be profiling it later). Anyway, I found a solution with two edges (it is solving my problem but makes me sacrifice the use of ajax) :
So Instead of calling - from each managed bean - the method (prepareList()) which I use as listener:
private DataModel items = null; // Getter to retrieve items
// ......
public String prepareList() {
recreatemodel();
return "List";
}
private void recreatemodel(){
items=null;
}
(by the way, this method sets the datamodel to NULL to refresh it, and that is how my datatables get refreshed).
Inside the command button I nested property action listener:
<h:commandButton image="#{resource['images/search.png']}" id="searchbutton" value="#{bundle.Search}"
action="submit"
disabled="#{empty ddnController.patientID or ddnController.patientID.equals('0')}">
<f:PropertyActionListener target="#{ddnController.items}" value="#{null}" />
<f:PropertyActionListener target="#{evalController.items}" value="#{null}" />
<f:PropertyActionListener target="#{corController.items}" value="#{null}" />
<!--...etc -->
</h:commandButton>
I wish <f:PropertyActionListener /> could be nested inside <h:ajax/>.
If somebody has a solution that allows to use property action listener and ajax to avoid submitting the form with a button, s/he is welcome. I'll make then his/her answer as accepted.

Resources