Richfaces and JSF/AJAX Lifecycles - jsf

I´ve managed to get the code to do what I intended, but I do not understand a particular aspect of why this works. I´m running Seam 2.2.2 with Richfaces 3.3.3.
Here is the code from the xhtml page:
...
<h:form id="radiobuttontestform">
<fieldset>
<h:panelGrid columns="3">
<h:selectOneRadio layout="pageDirection" id="myRadio" value="#{actionBean.myRadioButton}">
<f:selectItem itemLabel="First" itemValue="0" />
<f:selectItem itemLabel="Second" itemValue="1" />
<a4j:support event="onclick" ajaxSingle="true" process="myDropdown" reRender="myDropdown,myCount,test" />
</h:selectOneRadio>
<h:panelGrid columns="1" border="0">
<h:selectOneListbox size="1" id="myDropdown" value="#{actionBean.rowCountPredefined}" disabled="#{actionBean.myRadioButton != '0'}">
<f:selectItem itemLabel="10" itemValue="10" />
<f:selectItem itemLabel="20" itemValue="20" />
<f:selectItem itemLabel="30" itemValue="30" />
</h:selectOneListbox>
<h:inputText id="myCount" maxlength="5" value="#{actionBean.rowCountSpecified}" disabled="#{actionBean.myRadioButton != '1'}" required="true">
<f:validateLongRange minimum="1" maximum="1000" />
<rich:ajaxValidator event="onkeyup" for="myCount" />
</h:inputText>
<rich:message id="errorMessage" for="myCount" ajaxRendered="true" showDetail="false" showSummary="true">
<f:facet name="errorMarker">ERROR:</f:facet>
</rich:message>
</h:panelGrid>
</h:panelGrid>
</fieldset>
<h:outputLabel id="test" value="RadioValue: #{actionBean.myRadioButton}" />
<a4j:commandButton id="show" value="Show Values in Log" action="#{actionBean.showValues}" />
<a4j:commandButton id="done" value="Save and end conversation" action="#{actionBean.apply}" />
</h:form>
...
The backing bean is just a simple POJO with getters and setters for the three properties here. (myRadioButton, rowCountPredefined, rowCountSpecified)
This is what I get: (the correct result)
radio button example http://katzekat.de/Bilder/radio2.png
radio button example http://katzekat.de/Bilder/radio.png
Here is my thinking:
Setting ajaxSingle to true means that only the radio button will be processed on the server. The dropdown next to it doesn´t need validation - it will always contain a correct value. I´ve added the process="myDropdown" in order to persist the value into the backing bean, otherwise when I switch the radio button to position 2 the dropdown reverts to its original value. (I realise this is only cosmetic!) I´ve checked this with a debugger and it does indeed set the property in the backing bean and everything is working as expected.
Once the radio button is switched into position 2 a value can be entered in the textbox and will be validated. This works perfectly, and when I switch the radio button back to position 1, the validation error is cleared if this field is in an error state. Presumably because the error message is only present in the request scope.
Firing up the debugger again when the radio button is in position 2 and entering a valid value in the text field reveals no update on the backing bean when switching back to position 1. I also expected this as I´m telling only the radio and the dropdown to process on the server. This is the bit I don´t understand though - the value in the textfield is persisted on postback. (See 2nd link above) Where is this value for this textfield saved if not in the backing bean ?

Submitted form values are stored in component on Apply Request Values phase.
For example in your case javax.faces.component.html.HtmlInputText#decode method of the textfield calls javax.faces.component.UIInput#setSubmittedValue. The submitted values are not set to the bean (as you expected) as the component is not included to execute part. Then inputText's renderer re-displays (writes to the response) the submitted values.
It works pretty the same when validation fails. Submitted values are stored on Apply Request Values phase, and then because of failed validation the submitted values are not set to beans (Update Model Values phase is skipped), then the submitted values are re-displayed.

Related

Primefaces dataTable filter selectOneMenu not working

I am using PrimeFaces 5.1, In my project dataTable to filter used.In text filter is work fine but dropdown filter is not working properly (i.e) In dropdown I show department,First time I choose any value from dropdown is work fine anothertime I choose dropdown It not return any value show in dataTable.I choose select one first value from dropdown also throw null pointer exception.
<p:dataTable id="datalist" widgetVar="datalist" var="user" value=#{beanList.userList}>
<p:column headerText="Department" filterBy="#{user.deptname}"
filterMatchMode="exact" >
<f:facet name="filter">
<p:selectOneMenu onchange="PF('datalist').filter()">
<f:selectItem itemLabel="ALL" itemValue="#{null}"
noSelectionOption="true" />
<f:selectItems value="#{datalist.deptList}" />
</p:selectOneMenu>
</f:facet>
<h:outputText value="#{user.depatname}" />
</p:column>
</p:dataTable>
My doubt is default value ALL click and second time select any value return null or no data show in dataTable.
Since I don't know the scope of your Managed Bean: Try a scope longer than request (see PrimeFaces 5.1 User Documentation), and provide a value "filteredValue" for your table, like this:
<p:dataTable id="datalist" widgetVar="datalist" var="user"
value="#{beanList.userList}" filteredValue="#{beanList.filteredUserList}">
With that, you make sure to keep your filtered table/list in a field in your managed bean and the contents won't get lost.
Also, make sure your Managed Bean class is serializable (See this stackoverflow post)

Rerender multiple h:panelGrid on change of h:selectOneMenu in JSF 1.2

The situation:
I want to display specific panelGrid(s) on the page based on drop-down selection. I am doing this by storing several boolean which get set to true/false based on which item is selected in the drop down. I use the onchange="submit()" to refresh/re-render the page.
The problem:
I have validation on many fields in the form, so if I select an item it does validation and will not display the form.
The question:
How do I get the selectOneMenu change to re-render only the set of controls on the page being impacted instead of the whole page and causing validation?
The code: (JSF 1.2)
<h:selectOneMenu id="list" value="#{sessionBean.myDecorator.selectedItem}"
onchange="submit()" immediate="true" required="true"
valueChangeListener="#{requestBean.listChanged}">
<f:selectItem itemValue="#{null}" itemLabel="--Select One--" noSelectionOption="true" />
<f:selectItems value="#{sessionBean.myDecorator.mapItems}" />
</h:selectOneMenu>
Field causing validation:
<h:inputTextarea id="lblRequiredField" cols="100" rows="3" required="true" immediate="true"
value="#{sessionBean.myDecorator.myDo.myField}">
<f:validateLength minimum="1" maximum="300" />
</h:inputTextarea>

JSF inputText's value reappears after clearing it

I have to validate that a h:inputText has a value. There for I'm using the required="true" on that component. It does the job and it works, but then something strange happens.
When I leave it blank, the required="true" happens. When I type some text in the inputText, the required="true" does not happen. When I, after adding text, remove the text the required="true" happens, but the previously entered value reappears in the inputText.
I don't really have got an idea what this could be. Note that when I'm saying the "required="true"" happens, I mean that the border of the inputText gets red (see code).
Here is the code:
<h:form id="generateLetterForm">
<h:panelGroup id="submitterPanel">
<h:panelGrid styleClass="rSplitPanel1" columns="1">
<e:inputText entityBB="#{entityBB}" type="#{type}"
property="submitterFirstName" />
<e:inputText entityBB="#{entityBB}" type="#{type}"
property="submitterLastName" />
</h:panelGrid>
<h:panelGrid styleClass="rOnePanel" columns="1">
<h:panelGroup>
<h:outputText value="#{AppMessages[type.concat('.address')]}"
styleClass="Fieldname" />
<h:panelGrid columns="3" cellpadding="2" cellspacing="0"
styleClass="Fieldcontent"
columnClasses="rAddressStreet, rAddressStreetNr, rAddressBoxNr">
<h:panelGroup>
<h:inputText id="submitterStreetName"
value="#{entityBB.entity.address.street}" required="true" styleClass="#{component.valid ? '' : 'addressError'}" />
<rich:tooltip target="submitterStreetName">
<h:outputText
value="#{AppMessages[type.concat('.submitterStreetName')]}" />
</rich:tooltip>
</h:panelGroup>
"2 other similar columns" (would make code to complex for the problem)
</h:panelGrid>
</h:panelGroup>
</h:panelGrid>
</h:panelGroup>
<a4j:commandButton value="#{AppMessages['general.action.save']}"
actionListener="#{entityBB.createStandardLetter()}"
render="generateLetterForm messages letterExistsPanel"
status="ajaxStatus" styleClass="floatRight"/>
</h:form>
EDIT: The first 2 input text fields (e:inputText) are my own components. Nothing goes wrong there.
The backing bean is ViewScoped
When you enter the form properly the value is stored in the attribute in the ViewScoped bean. When you then enter the form incorrectly, the 'Process Validations' phase will throw up an error which means the 'Update Model Values' phase is not executed, so the value in the ViewScoped bean remains the original one that was entered when you entered the form correctly and it is this value that is redisplayed when the view is rendered.
The problem is located, though not fixed because the possible fix (setting the context-param to false) may not happen. I'm guessing this behaviour can be seen as a bug in JSF?
In the web xml:
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-n‌​ame>
<param-value>false</param-value>
</context-param>

Check box and Radio Button selection gets cleared on h:selectOneMenu value change

I am working on a form which has two datatables. In the first datatable, I am displaying the radio buttons and checkboxes, whereas the second datatable contains
selectOneMenu(s). Value change listener has been implemented on the selectOneMenu and on value change, the subsequent fields gets populated based on the selection.
Everything works fine except that when I select the value from the dropdown, the checkbox and the radio button values are cleared.
f:ajax event="change" has been used for the change event on selectOneMenu. Looks like the whole page gets refreshed and the values are cleared.
I also tried using f:ajax by updating the id of the datatable in which the selectOneMenu is present.
<p:dataTable styleClass="borderless" id="inResultTable" var="result" value="#{RequestBean.fooFields}" rendered="#{not empty RequestBean.fooFields}">
<p:column style="width:150px;">
<f:facet name="header">
<h:outputText value=" " />
</f:facet>
<h:outputText value="#{msg[result.fldLabel]}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="" />
</f:facet>
<ui:repeat value="#{RequestBean.fooFields}"
var="itm">
<h:selectOneMenu value="#{itm.indFieldValue}"
rendered="#{result.lvlid==itm.lvlid}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectOneMenu>
<h:selectOneRadio value="#{itm.indFieldValue}" rendered="#{result.lvlid==itm.lvlid and result.fldType=='radio'}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectOneRadio>
<h:selectManyCheckbox value="#{itm.indFieldCheckBox}" rendered="#{result.lvlid==itm.lvlid and result.fldType=='selectbox'}">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectManyCheckbox>
</ui:repeat>
</p:column>
</p:dataTable>
<p:dataTable styleClass="borderless"
id="resultTable" var="result"
value="#{RequestBean.depFields}">
<h:selectOneMenu value="#{RequestBean.field4Value}"
valueChangeListener="#{RequestBean.processValueChange4}"
rendered="#{result.lvlid=='5' and result.fldType=='selectbox'}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItem itemLabel="--Please Select--" itemValue="#{null}" />
<f:selectItems value="#{RequestBean[result.field]}" />
<f:ajax event="change" render="#form" />
</h:selectOneMenu>
...
...
</p:dataTable>
N.B: The requirement is such that the datatable with checkbox and radio buttons has to be placed at the top. IDs cannot be used for the selectOneMenu in the second table since I am
populating the selecOneMenu(s) dynamically based upon the entries in the database.
I know that this might be a simple issue but didn't have any luck with the info posted on most websites.
Any help would be appreciated.
Here's your <f:ajax>.
<f:ajax event="change" render="#form" />
You didn't specify the process attribute. So it defaults to #this, which means that only the current input component is processed during submit. However, you specified a render of the whole form. So the whole form will be refreshed. However, the other input components aren't been processed during submit. So their model values won't be updated, which means that during render response the initial values will be redisplayed instead of the submitted values, which are in your case apparently blank/null.
You've basically 2 options:
Process the whole form during submit.
<f:ajax process="#form" render="#form" />
Or, update only those components which really needs to be updated.
<f:ajax render="clientId1 clientId2 clientId3" />
In your particular case I think option 2 isn't viable, so option 1 is the best one. Please note that I omitted the event attribute. It defaults to change already.
Unrelated to the concrete problem, I'm not sure what you're all doing in your value change listener method, but I only want to note that most starters abuse it for the purpose of manipulating the model values and that it don't always work quite as expected (changed model values are not reflected at all). If this is true in your case, then you should actually be using <f:ajax listener> instead.
See also:
When to use valueChangeListener or f:ajax listener?
The main reason for the values of Check boxes & Radio buttons getting cleared after a value change listener could be that the model values are not updated.
Value change listeners are called before updating the model.
For these kind of issues, it is very important to have an understanding of the JSF lifecycle.
Please try following code in your value change listener and see.
public void valueChange(ValueChangeEvent event){
PhaseId phase = event.getPhaseId();
if (phase.equals(PhaseId.ANY_PHASE))
{
event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
event.queue();
return;
}
if(!phase.equals(PhaseId.UPDATE_MODEL_VALUES))
{
return;
}
// Your code
}
I didn't try this code with your example. Please let me know with complete example source code if it is not working.
Thanks.

Dynamically changing the visibility of the JSF components

My requirement is like this: I am having a text input and whenever a value change event occurs, a select many list box has to be populated. If there is no matching records found, then a text input has to appear instead of a select many list box.
<h:column>
<h:selectManyListbox size="3" value="#{hostInfoBean.gateKeeperendPointReference}" rendered="#{hostInfoBean.selectManyRendered}" id="gateKeeperendPointReference">
<f:selectItems value="#{hostInfoBean.gateKeeperendPointReferenceItems}" />
</h:selectManyListbox>
<h:inputText id="gateKeeperendPointReferenceText" size="30" rendered="#{!hostInfoBean.selectManyRendered}">
</h:inputText>
</h:column>
Also I am using a4j for the value change listener,
<a4j:support event="onchange" reRender="hostInfo:gateKeeperendPointReference" focus="GFacPath"
ajaxSingle="true" />
'selectManyRendered' is a boolean value which I am determining in the JAVA bean. The program works only for the default value of the boolean variable. If the boolean value is changed during runtime, then the toggle between the visibility of selectManyListbox and inputText is not working. Please help to fix this. Am i missing something?
regards,
Suresh
If the "rendered" attribute resolves to false, then the component isn't in your tree and can't be found as a "rerender" target. When you have components that are rendered conditionally you want to wrap them in a component that is always available as a target, like so:
<h:inputText value="#{myBean.text}" >
<a4j:support event="onkeyup" reRender="listZone" ajaxSingle="true" />
</h:inputText>
<h:panelGroup id="listZone">
<h:selectManyListbox value="#{myBean.list}" rendered="#{myBean.renderList}" >
<f:selectItems value="#{myBean.listItems}" />
</h:selectManyListbox>
<h:inputText size="30" rendered="#{!myBean.renderList}/>
<h:panelGroup id="listZone">

Resources