valueChangeListener isn't always triggered depending on the rendered attribute - jsf

I'm having trouble to understand why valueChangeListener isn't triggered.
I came accross this topic valueChangeListener Not fired when rendered/disabled attribute is added
but it didn't help so much.
When my xhtml is this :
<h:inputText value="#{cm.reference}"
rendered="#{cm.endDate eq null}"
valueChangeListener="#{userDataBean.ContactMethodChanged}" />
it's working (I mean the valueChangeListener is triggered)
But when I try this :
<h:inputText value="#{cm.reference}"
rendered="#{cm.contactMethodId eq param.contactMethodID}"
valueChangeListener="#{userDataBean.ContactMethodChanged}" />
it doesn't.
Unfortunately I need to have the second option working.
More info :
I'm inside a h:dataTable where I iterate on a list of ContactMethod (cm)
UserDataBean is applicationScoped
Apache Tomcat 7.0
JSF 2.2 (Mojarra 2.2.0)
Thank you for any help.

If the input is not processed during the form submit, then that can only mean that the rendered attribute didn't evaluate true during processing the form submit, which in turn can only mean that the #{cm.contactMethodId} has incompatibly changed (e.g. because it's a request scoped bean property instead of a view scoped bean property) and/or that #{param.contactMethodID} isn't present during the form submit.
Provided that the bean is in the right scope for the job (otherwise the original rendered approach would likely not have worked either), then retaining the request parameter as follows in the command button/link responsible for submitting the form should do it:
<h:commandButton ...>
<f:param name="contactMethodID" value="#{param.contactMethodID}" />
</h:commandButton>

Related

How to update value of EditableValueHolder in action listener?

I have this JSF (Java EE 7, provided by GlassFish 4.1 + PrimeFaces 5.1) form containing database connection information like host name, port number, etc. Also part of this form is a URL field. I want this field to be editable, but I also want to be able to set the value based on the other fields.
To do so I created a button with an action listener where I'm reading the posted data from the request parameter map and generate the new URL value. Then I want to put the new value in the URL field and use that value instead of the posted data. What I tried is to get the component as EditableValueHolder and set the submitted value and render the response. I also tried setting the component's value and calling resetValue.
The best result was the URL field being updates after two clicks.
XHTML:
<p:inputText id="url"
size="50"
value="#{database.url}"/>
<p:commandButton icon="ui-icon-arrowrefresh-1-w"
immediate="true"
actionListener="#{database.createConnectionURL('namingContainer')}">
<p:ajax update="url" />
</p:commandButton>
Bean (using OmniFaces):
UIComponent urlComponent = Faces.getViewRoot().findComponent(namingContainer + "url");
if (urlComponent instanceof EditableValueHolder) {
EditableValueHolder editValHolder = (EditableValueHolder) urlComponent;
editValHolder.setSubmittedValue(urlValue);
}
Faces.getContext().renderResponse();
The immediate="true" is a leftover from JSF 1.x, when it was not possible to process only a specific set of inputs and/or buttons. It was then more than often abused to process only a specific set of inputs and/or buttons instead of to prioritize validation. You'd better not use it when you've JSF2 ajax at hands.
With JSF2 ajax you can just use execute="..." or in case of PrimeFaces process="..." to execute/process only a specific set of inputs/buttons.
<p:inputText id="url"
size="50"
value="#{database.url}" />
<p:commandButton icon="ui-icon-arrowrefresh-1-w"
process="#this"
action="#{database.createConnectionURL('namingContainer')}"
update="url" />
Then you can just update the model value.
public void createConnectionURL(String namingContainer) {
// ...
url = urlValue;
}
Note that I moved back <p:ajax update> into the <p:commandButton>. Perhaps you was mixing with <h:commandButton>.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
Unrelated to the concrete problem, to deal with components with OmniFaces, better use Components utility class.

How does JSF load property values of managed bean?

I am a JSF beginner. I have a question about managed bean.
Step 0:
There is a managed bean BeanA, scope is request. And BeanA instance1.propertyA = "0";
Step 1:
using ajax to change country, then in BeanA.countryChanged method, change managed bean BeanA.propertyA = "A".
<t:selectOneMenu id="Country" required="true" valueChangeListener="#{BeanA.countryChanged}">
<a4j:support event="onchange" limitToList="true" ajaxSingle="true" />
<f:selectItems value="#{BeanA.countries}" />
</t:selectOneMenu>
Step2:
submit form to do validate a text input
<h:inputText id="street" required="#{BeanA.propertyA == "A"}"
I expect that in step2 the value propertyA of BeanA instance2 should be "A" in JSF validate phase, but actually it is "0". I don't know how does JSF load BeanA instance property values to create new BeanA instance. And what should I do, the value will changed to "A"? Thanks,
The symptoms indicate that your bean is request scoped. This means that it's reconstructed on every single HTTP request. You probably didn't realize that every single ajax request also counts as a separate HTTP request. In effects, you're not reusing the same bean instance across ajax postbacks on the same view. Every time a brand new instance is been created, with all its properties set to default.
JSF 2.0, which is designed with ajax in mind, has solved it with the new view scope in the standard API.
In JSF 1.x, you need to fall back to 3rd party component libraries. In your particular case, given that you're using both Tomahawk and Ajax4jsf, you've 2 options:
Use <t:saveState>.
<t:saveState value="#{BeanA}" />
Or, use <a4j:keepAlive>.
<a4j:keepAlive beanName="BeanA" />

Why does a h:commandButton fail to submit the form if it's parent is dynamically rendered?

This JSF1 code has me totally puzzled for hours. The basic setup is this page displayed with Seam2:
<h:form encType="multipart/form-data">
<rich:dataTable value="#{results}">
...
</rich:dataTable>
<h:selectOneMenu value="#{contact.type}">
<s:selectItems value="#{contactTypes}" var="t" label="#{t.label}" />
<s:convertEntity />
<a4j:support event="onchange" reRender="submitControls" />
</h:selectOneMenu>
<h:selectOneMenu value="#{template}">
<s:selectItems value="#{allTemplates}" var="t" label="#{t.label}" />
<s:convertEntity />
<a4j:support event="onchange" reRender="submitControls" />
</h:selectOneMenu>
<a4j:outputPanel id="submitControls" layout="block">
<a4j:outputPanel rendered="#{null != results and results.size gt 0 and ('ONE' == contact.type.label or template != null)}">
<h:commandButton value="submit" action="#{manager.generate}" />
</a4j:outputPanel>
<h:outputText value="Search first" rendered="#{results == null or results.size == 0}" />
<h:outputText value="Select template first" rendered="#{'ONE' == contact.type.label and template == null}" />
</a4j:outputPanel>
</h:form>
Obviously, the original page is a bit larger. What has me scratching my head is that if I don't change contact.type (leave it at a default selected by the backing bean) the form submits fine. If I switch the type to ONE this correctly renders the "Select template first" text instead of the submit control. Restoring the submit button by selecting another type re-produces the <input> BUT without the onclick handler that was there when the form was first rendered.
Now a click on the <h:commandButton> sends a request to the server but does NOT trigger the associated action. However, it now restores the onclick handler and a second click triggers a proper submit.
I'm at a loss why this is so. Any suggestions?
EDIT: moving the rendered attribute to the button results in the same behavior (even if it did work, the original panels contain more controls that share the same condition, so they do serve a purpose)
EDIT2: I've just tested that simply re-adding the "lost" onclick handler (via firebug) that gets rendered on the submit button makes the action work as intended. I'm beginning to suspect a bad interaction between richfaces and the trinidad libs also included in this project (but not used on this page).
It's a safeguard against tampered/hacked requests. Otherwise a hacker would be able to invoke actions s/he isn't allowed to invoke by just editing the sent HTTP request parameters accordingly that the non-rendered (e.g. due to missing "ADMIN" role) command button will be invoked.
You need to make sure that you prepare the same model (managed bean instance with all properties responsible holding the conditions behind rendered attribute) during the HTTP request of processing the form submit as it was during the HTTP request of displaying the form. In JSF2, this is easy achievable by placing the bean in the view scope instead of the request scope. The view scope lives as long as you're interacting with the same view. In JSF1, you'd need to grab a 3rd party framework tag like Tomahawk's <t:saveState> or RichFaces' <a4j:keepAlive> in order to simulate the JSF2 view scope.
<a4j:keepAlive beanName="results" />
The same story applies to disabled attribute by the way.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
JSF 1.2: How to keep request scoped managed bean alive across postbacks on same view?
I think that with the rendered attribute and anything inside you have to take care that the evaluation of it is the same on the initial request AND the submit. It may change just before the render phase but if its not the same during application invoke it will most likely ignore the action if in this phase the button would not be rendered.
As far as i remember this happend for me mostly when the rendered expression uses something like an entity attribute that will be changed during the apply request values phase already.

Binding a JSF bean to a included JSF

I'm at the end of my rope with this one. I'm new to JSF so this is probably my misunderstanding of a lot of stuff.
<ui:composition>
<f:view>
<tr:form>
<ui:fragment rendered="#{param['type'] eq 'myType'}">
<ui:include src="/home/myPage.jspx" />
</ui:fragment>
......
I pass the page a certain type, it display's certain fields/criteria for a form and a bean backs it all because there is a single search.
Within myPage.jspx I have:
action="#{MyBean.submitForm}"
does not work, although a onsubmit="alert('hi');" does work as an attribute of the form element.
I guess what's most confusing is that
valueChangeListener="#{MyBean.stateChanged}"
does work on a field in the myPage.jspx
Why does the action (attribute of a button) not work?
During processing of the form submit, if the button or one of its parent components is not rendered, then the button's action won't be invoked. You need to make sure that the rendered attribute evaluates the same during processing of the form submit as it did when the form was displayed. In your case, you're depending on the value of a request parameter with the name type.
In this particular case, you could solve the problem by retaining the request parameter type by a <f:param> nested in the command button:
<h:commandButton ...>
<f:param name="type" value="#{param.type}" />
</h:commandButton>
Or, if you're using JSF 2.0, placing the bean in the view scope and setting the type parameter in the managed bean by <f:viewParam> can also solve it.
<f:metadata>
<f:viewParam name="type" value="#{bean.type}" />
</f:metadata>
...
<ui:fragment rendered="#{bean.type eq 'myType'}">
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated

What is the JSF behaviour, if you bind the same backing bean property to two input fields in the same form?

Is there a defined behaviour in JSF, if two input fields are bound to the same session scoped Backing Bean property.
Here is my code snippet
<h:form id="myForm">
<h:inputText id="field1" value="#{TheBackingBean.theProperty}" />
<h:inputText id="field2" value="#{TheBackingBean.theProperty}" />
<h:commandButton id="continueButton" action="#{TheBackingBean.doSomething}" />
</h:form>
My question: If field1 and field2 receive different values, what will be bound to the backing bean property? Is this even allowed?
I know this is a crude scenario. My motivation is, that we have htmlunit tests running for our application. In our JSF application we want to use a cool ajaxified custom component. This doesnt work together very well with htmlunit. So my idea was, I just put in a hidden field that binds to the same property. The unit test then fills the hidden field instead of the "real" thing.
Regards
I think this kind of code is allowed, but I am not sure of the value of theProperty after the submission. What I think is that JSF will do the following:
TheBackingBean.setTheProperty(field1.value);
TheBackingBean.setTheProperty(field2.value);
However, nothing - as far as I know - specifies the order of the setter calls. Thus, after the update values JSF phase, you will not be sure if theProperty will be equal to field1.value or field2.value.
Concerning your scenario, you say that you want to bind the same property to an inputText and an hiddenText. As the hiddenText will not submit its value, unlike the inputText, this problem will not occur. Indeed, if you have this kind of JSF code:
<h:inputText id="field1" value="#{TheBackingBean.theProperty}"/>
<h:inputHidden id="field2" value="#{TheBackingBean.theProperty}"/>
then JSF will only do:
TheBackingBean.setTheProperty(field1.value);
during the submission phase.

Resources