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

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

Related

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

JSF Ajax method does not persist variable in bean

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

Can you update an h:outputLabel from a p:ajax listener?

I'm trying to use a p:ajax tag and then in that listener, i'm setting a value called "periodRendered". then i'm trying to update an h:outputLabel tag via an update from the p:ajax tag. It's not updating ajaxily and i'm thinking it's because a primefaces ajax tag can't update a standard jsf outputLabel tag.
Is my assumption correct and is there a more appropriate tag i should be using instead of h:outputLabel ?
<h:outputLabel for="addProgramTo" value="Add Program To" />
<p:selectOneMenu value="#{ppBacker.grantProgram.grant_project_id}" id="addProgramTo" size="1" styleClass="listBoxMedium">
<p:ajax process=":addProgram:addProgramTo" update=":addProgram:periodGrid, :addProgram:periodLabel" event="change" listener="#{ppBacker.addProgramListener}" />
<f:selectItems value="#{ppBacker.grantProjectDropDownList}" />
</p:selectOneMenu>
<h:outputLabel for="period" value="Period" id="periodLabel" rendered="#{ppBacker.periodRendered}">
You cannot update elements which are not rendered , rendered=false "is a JSF way to" to remove elements from the DOM Tree ,
its not like css display:none or visibility:hidden <- this two will keep the elements in the DOM tree but hidden , while the JSF rendered=false wont even render (keep) the element in the DOM tree (you wont even see it in the "view source" of the page)
So in you case you need to wrap the outputLabel with `panelGroup' and update the id of the wrapper
<h:panelGroup id="periodLabelWrapper">
<h:outputLabel for="period" value="Period" id="periodLabel" rendered="#{ppBacker.periodRendered}">
</h:panelGroup>
and refer to the wrapper (which always be in the DOM tree) id in the <p:ajax update attribute, like this:
<p:ajax process=":addProgram:addProgramTo" update=":addProgram:periodGrid, :addProgram:periodLabelWrapper" event="change" listener="#{ppBacker.addProgramListener}" />
Another solution would be the update the entire form like this <p:ajax update="#form" ... that way you don't need the wrap the outputLabel
regarding your comment question
how does #form update the un-rendered elements, but targeting them directly through id's does not?
You can't target an element in update which is not present in the page (rendered=false) "its not there"
But when you use update="#form" or update="someWrapperID" the form/wrapper "re evaluates" all its inner elements , including the ones with rendered="#{someBean.someCondition}" and the condition gets "re evaluated" so if it result to true the elemet will be displayed...
I'm not sure the reason for this behavior, but I'm putting money on the fact that p:ajax is going to require an active target for the update to work. Here's an example of it working/not working:
<h:body styleClass="center">
<f:view contentType="text/html">
<h:form id="test">
<h:outputLabel for="addProgramTo" value="Add Program To: " />
<h:selectOneMenu id="addProgramTo" value="#{testScope.target}">
<p:ajax update=":test:periodLabel, :test:wrapper" event="change" process="#form">
</p:ajax>
<f:selectItems value="#{testScope.values}"/>
</h:selectOneMenu>
<hr />
<p:outputPanel id="wrapper">
<h:outputLabel value="Works, has a target" rendered="#{testScope.timeToRender}"/>
</p:outputPanel>
<hr />
<h:outputLabel value="does not work" id="periodLabel" rendered="#{testScope.timeToRender}" />
</h:form>
</f:view>
</h:body>
//Bean...
#ViewScoped
#ManagedBean(name = "testScope")
public class TestScope
{
private String[] values = { "False", "What?", "True" };
private String target = "Nothing";
/**
* #return the target
*/
public String getTarget()
{
return target;
}
/**
* #return the values
*/
public String[] getValues()
{
System.out.println(values);
return values;
}
public boolean isTimeToRender()
{
return "True".equals(target);
}
/**
* #param target the target to set
*/
public void setTarget(String target)
{
this.target = target;
}
}
I don't have the time to dig into this one, but from a quick look (again QUICK) in the debugger it looks like it doesn't find the ID (it isn't rendered) so it doesn't get the update. Why? I'm not sure--the easy workaround is to place it inside something you can update (p:outputPanel) and render it as a span, then your code should work. Is this acceptable? Not really...
If you can deal with a full form update the following will work as well ->
<p:ajax update=":test" event="change" process="#form">
Since you're targeting the enclosing form it updates all the children. If I was doing this, that is the workaround I'd use. It isn't a lot of data and it is a heck of a lot cleaner. I'm not sure if this a bug or a feature. It feels buggy though.
Short answer: yes you can target a label. Long answer: you can't target one that isn't rendered. I really hope this helps.

render page title using jsf 2

is there any way to include the page's title inside an f:ajax tag, so that its content is also updated at run time?
currently my f:ajax tag looks like this -
<f:ajax render="#form">
i tried to add an id to the h:head tag, and add that id to the 'render' property of the f:ajax tag, but if i do so i get an error when the page loads -
<f:ajax> contains an unknown id 'pageHead' - cannot locate it in the context of the component B1
cheers,
eRez
Interesting question. I think there is no such command in render of ajax (like #form) to re-render the page title. What you can do is to wrap <title> with <h:form> or other "grouping" component (eg. h:panelGroup as Daniel said) like this :
<h:form id="titleForm">
<title>#{fooBean.fooTitle}</title>
</h:form>
And then call ajax update eg. with button :
<h:commandButton immediate="true" value="Change title">
<f:ajax event="click" render=":titleForm" listener="#{fooBean.changeTitle}"/>
</h:commandButton>
Bean:
private String fooTitle;
public void changeTitle() {
this.fooTitle= "updatedTitle";
}
// getter/setter
I don't know what else could you do, this should work. So wrap your title with <h:form id="..."> and then render it from ajax.

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.

Resources