Conditionally render another component based on selectOneMenu value [duplicate] - jsf

Is there a way to render a component based on the current value the user has selected from a selectOneMenu component? My selectOneMenu component is populated with an enum consisting of two values, smoker and non-smoker. If the user has smoker selected I want to render a checkbox below it which lets the user check how many they smoke a day 10, 20, 30+, etc. I also want the opposite to work if they user has selected non-smoker i.e. the check boxes don't render/disappear.

Just check the dropdown menu's value in the rendered attribute of the target components and update their common parent by a <f:ajax>. Here's a kickoff example:
<h:selectOneMenu value="#{bean.item}">
<f:selectItem itemValue="one" />
<f:selectItem itemValue="two" />
<f:selectItem itemValue="three" />
<f:ajax render="results" />
</h:selectOneMenu>
<h:panelGroup id="results">
<h:panelGroup rendered="#{bean.item eq 'one'}">
You have selected "one".
</h:panelGroup>
<h:panelGroup rendered="#{bean.item eq 'two'}">
You have selected "two".
</h:panelGroup>
<h:panelGroup rendered="#{bean.item eq 'three'}">
You have selected "three".
</h:panelGroup>
</h:panelGroup>
If you'd like to perform some business logic based on the selected value, use <f:ajax listener>.
<f:ajax listener="#{bean.changeItem}" render="results" />
public void changeItem() {
someResult = someService.getByItem(item);
}
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
How to load and display dependent h:selectOneMenu on change of a h:selectOneMenu
Conditionally displaying JSF components

Related

Validation on checkbox and input field in jsf [duplicate]

I have a form which contains a dropdown and two input fields.
<h:selectOneMenu />
<h:inputText />
<h:inputText />
I would like to make the required attribute of the input fields conditional depending on the selected value of the dropdown. If the user chooses the first item of the dropdown, then the input fields must be required. If the user chooses the second item, then those would not be required.
How can I achieve this?
Just bind the dropdown to the view and directly check its value in the required attribute.
<h:selectOneMenu binding="#{menu}" value="#{bean.item}">
<f:selectItem itemValue="first" itemLabel="First item" />
<f:selectItem itemValue="second" itemLabel="Second item" />
</h:selectOneMenu>
<h:inputText value="#{bean.input1}" required="#{menu.value eq 'first'}" />
<h:inputText value="#{bean.input2}" required="#{menu.value eq 'first'}" />
Note that the binding example is as-is. Do absolutely not set it to a bean property here. See also How does the 'binding' attribute work in JSF? When and how should it be used?
Also note that the ordering of the components is significant. If the menu is located below the inputs in the tree, use #{menu.submittedValue eq 'first'} instead. Or if you want to be independent from that, use #{param[menu.clientId] eq 'first'} instead.
Assuming you are using JSF 2.0: Let your SelectOneListBox execute with ajax and re-render the input fields on change of the list box:
A quick sketch:
<h:selectOneMenu value="#{myBean.myMenuValue}">
<f:ajax render="input1"/>
..
</h:selectOneMenu>
<h:inputText id="input1" value="#{myBean.myInputValue}"
required="#{myBean.myMenuValue == 'firstEntry'}" />

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>

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.

Conditionally render a component based on selectOneMenu value

Is there a way to render a component based on the current value the user has selected from a selectOneMenu component? My selectOneMenu component is populated with an enum consisting of two values, smoker and non-smoker. If the user has smoker selected I want to render a checkbox below it which lets the user check how many they smoke a day 10, 20, 30+, etc. I also want the opposite to work if they user has selected non-smoker i.e. the check boxes don't render/disappear.
Just check the dropdown menu's value in the rendered attribute of the target components and update their common parent by a <f:ajax>. Here's a kickoff example:
<h:selectOneMenu value="#{bean.item}">
<f:selectItem itemValue="one" />
<f:selectItem itemValue="two" />
<f:selectItem itemValue="three" />
<f:ajax render="results" />
</h:selectOneMenu>
<h:panelGroup id="results">
<h:panelGroup rendered="#{bean.item eq 'one'}">
You have selected "one".
</h:panelGroup>
<h:panelGroup rendered="#{bean.item eq 'two'}">
You have selected "two".
</h:panelGroup>
<h:panelGroup rendered="#{bean.item eq 'three'}">
You have selected "three".
</h:panelGroup>
</h:panelGroup>
If you'd like to perform some business logic based on the selected value, use <f:ajax listener>.
<f:ajax listener="#{bean.changeItem}" render="results" />
public void changeItem() {
someResult = someService.getByItem(item);
}
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
How to load and display dependent h:selectOneMenu on change of a h:selectOneMenu
Conditionally displaying JSF components

required attribute of inputText should depend on submitted value of another component

I have a form which contains a dropdown and two input fields.
<h:selectOneMenu />
<h:inputText />
<h:inputText />
I would like to make the required attribute of the input fields conditional depending on the selected value of the dropdown. If the user chooses the first item of the dropdown, then the input fields must be required. If the user chooses the second item, then those would not be required.
How can I achieve this?
Just bind the dropdown to the view and directly check its value in the required attribute.
<h:selectOneMenu binding="#{menu}" value="#{bean.item}">
<f:selectItem itemValue="first" itemLabel="First item" />
<f:selectItem itemValue="second" itemLabel="Second item" />
</h:selectOneMenu>
<h:inputText value="#{bean.input1}" required="#{menu.value eq 'first'}" />
<h:inputText value="#{bean.input2}" required="#{menu.value eq 'first'}" />
Note that the binding example is as-is. Do absolutely not set it to a bean property here. See also How does the 'binding' attribute work in JSF? When and how should it be used?
Also note that the ordering of the components is significant. If the menu is located below the inputs in the tree, use #{menu.submittedValue eq 'first'} instead. Or if you want to be independent from that, use #{param[menu.clientId] eq 'first'} instead.
Assuming you are using JSF 2.0: Let your SelectOneListBox execute with ajax and re-render the input fields on change of the list box:
A quick sketch:
<h:selectOneMenu value="#{myBean.myMenuValue}">
<f:ajax render="input1"/>
..
</h:selectOneMenu>
<h:inputText id="input1" value="#{myBean.myInputValue}"
required="#{myBean.myMenuValue == 'firstEntry'}" />

Resources