Can't render SelectManyCheckbox from my SelectOneMenu with an ValueChangeListener - jsf

I have a Map (Integer, List) which I want to fill from a JSF page. I'm only using JSF, no Primefaces or such.
On my JSF page there is a selectOneMenu that displays each keys of my Map, and a selectManyBox to choose the values for each key.
I want to be able to save each state before submitting the whole Map.
See my bean:
#ManagedBean(name="myBean")
#SessionScoped
public class MyBean implements Serializable {
(...)
public void refresh(ValueChangeEvent e)
{
if (idRole==-1){ //to check if its just the first selection
setKey((int)e.getNewValue());
}
else{
myObject.getMap().put(key,listOfValuesSelected); //put current manycheckbox values in last selected key
setKey((int)e.getNewValue()); //get new key
listOfValuesSelected=MyObject.getMap().get(Key); //refresh the
//selectManyCheckbox for the newly selected key
}
}
My JSF Page
<h:selectOneMenu id="idRole" value="#{myBean.key}" onchange="submit()" valueChangeListener="#{myBean.refresh}" render="checkbox"> >
<f:selectItem itemLabel="" itemValue="" />
<f:selectItems value="#{myBean.listKeys}" />
</h:selectOneMenu>
<fieldset id="checkbox">
<h:selectManyCheckbox value="#{myBean.listOfValuesSelected}">
<f:selectItems value="#{myBean.listeOfValues}" var="n"
itemLabel="#{n.title}" itemValue="#{n.key}"/>
</h:selectManyCheckbox>
</fieldset>
My real code is kind of a mess, I rearranged it a bit to fit the needs of my question but I can give you the real code if needed.
My problem is that the selectmanycheckbox doesn't "react" at all. I see that the listOfValuesSelected is modified when I am in debug mode.

Do you use AJAX somewhere? And what kind of form do you use?
With "doesn't react", do you mean it's not re-rendered, or that nothing happens when you select one or more items in it?
If you use AJAX then with the given code the select many checkbox will indeed not re-render (refresh). The reason is that SelectOneMenu doesn't have an attribute "render" that causes something to be re-rendered. Third party components often have such a thing, but the standard components only do that via an f:ajax tag. Also, you can't use a non-component ID as a re-render target. Fieldset is not a component.
See http://docs.oracle.com/javaee/6/tutorial/doc/gkabr.html on how to use f:ajax

Related

Is it possible to bind a value to more than one field?

I have the following piece of markup:
<h:selectOneMenu value="#{myBean.upperBound}">
<f:selectItems value="#{myBean.getValues(filterItem)}" />
</h:selectOneMenu>
And the following managedBean:
public class MyBean{
private FilterItem lowebBound;
private FilterItem upperBound;
public List<SelectItem> getValues(FilterItem filterItem){
//Some stuff
}
//GET, SET
}
How can I initialize the property lowerBound with the value that was selected in the selectOneMenu now. I need to reinitialize that value every time it's changed.
You need to keep the selectOneMenu and the property synched with an AJAX call.
One basic tutorial in the Oracle KB (visited 2015-04-13):
The f:ajax tag is a JavaServer Faces core tag that provides Ajax functionality to any regular UI component when used in conjunction with that component. In the following example, Ajax behavior is added to an input component by including the f:ajax core tag:
<h:inputText value="#{bean.message}">
<f:ajax />
</h:inputText>
Related reading:
The f:ajax listener method in h:selectOneMenu is not executed
Updating text component via selectOneMenu from inside a JSF2/Facelets subview
In your case, your component would look like this:
<h:selectOneMenu value="#{myBean.upperBound}">
<f:selectItems value="#{myBean.getValues(filterItem)}" />
<f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>
The listener method will be called when the action is performed; you can update the lowerBound inside it.
The name of the listener method that is called when a javax.faces.event.AjaxBehaviorEvent has been broadcast for the listener.

Set bean value on click of selectbooleancheckbox

I have a bean class and a selectBooleanCheckbox in xhtml page. I want that on the click of the box the value should be set in the backing bean.
Here is code:
<h:selectBooleanCheckbox id="provisioningTargetCollector"
value="#{targetSource.provisioningTargetCollector}">
</h:selectBooleanCheckbox>
Bean Class:
public boolean isProvisioningTargetCollector() {
return _provisioningTargetCollector;
}
public void setProvisioningTargetCollector(boolean provisioningTargetCollector) {
_provisioningTargetCollector = provisioningTargetCollector;
}
But the getter and setter are called only on page load. How can I set the value in bean method on click of checkbox.
The model with be filled with form data only when submit button will be pressed. If you want to do partial update to the server you need to send an AJAX request. Luckily, starting from JSF 2 it has been quite simple with the introduction of <f:ajax> tag. It adds ajax capabilities to UIComponent instances that implement the ClientBehaviorHolder interface, i.e. components that are capable of triggering ajax requests.
To do partial update of compenets you need to specify their client ids in execute attribute of <f:ajax> tag. As the default value of execute attribute evaluates to #this, or the component to which the tag is attached it. As soon as you want to update only the given <h:selectBooleanCheckbox> you can do it as simple as nesting a pure <f:ajax /> tag within you checkbox, i.e.:
<h:selectBooleanCheckbox id="provisioningTargetCollector" value="#{targetSource.provisioningTargetCollector}">
<f:ajax />
</h:selectBooleanCheckbox>

How to get value in JSF xhtml page from f:selectItems

I have select menu in JSF xhtml page. The select menu contains a
<h:selectOneMenu value="#{bean.statusFlag}">
<f:selectItems value="#{bean.statusList}"/>
</h:selectOneMenu>
The value is be being stored in status.
This works fine. I have to print the value in h:outputText in next column.
<h:outputText value="#{bean.statusFlag}" />
prints code rather value corresponding value of code, since the value is in statusList.
Is there any way to achieve this without having to modify the backing bean.
You could perhaps implement some sort of <f:ajax> within your <h:selectOneMenu>.
You could also use jquery with an onchange() event.
$('#select').change(function() {
$('#outText').val($('#select').val());
});
Hope that helps!

Adding dynamic drop down components in JSF

My requirement is like this. I have a selectMenu with some values (Examples: Engineering, Medicine, Law etc..,) . Suppose if I select Engineering in the drop down, I want another dropdown menu created dynamically which has values related to Engineering (Example: Electronics, Computers, Electricals etc..,). How do I achieve this in JSF 2.0 ?
You need to perform an ajax request when first h:selectOneMenu's selection change. This request will update the selectable items in the second h:selectOneMenu. After the ajax request, you must render the second h:selectOneMenu again, with the updated values.
Page:
<h:selectOneMenu value="#{bean.selectedSubject}">
<f:ajax listener="#{bean.changeSubject}" render="speciality_selection" />
<f:selectItems value="#{bean.subject}" />
</h:selectOneMenu>
<h:selectOneMenu id="speciality_selection" value="#{bean.selectedSpeciality}">
<f:selectItems value="#{bean.subjectSpecialities}" />
</h:selectOneMenu>
Managed bean:
public void changeSubject(){
//Loads the specialities depending on the selected subject
subjectSpecialities = loadSpecialitiesForSubject(selectedSubject);
}

JSF selectOneMenu is refreshing and going back to its previous state rather than showing the new value

I have a datatable where a lot of selectOneMenu items are available , for example, for 10 items each having one selectOneMenu combo. now if i click on any of the combos, they are supposed to save the value in the database and they do it. but after saving the changed value the selectOneMenu is returning back to its previous state. I want the selectOneMenu to keep its current state. also, the method is being invoked for every single combo in the datatable. i really wonder why!! i have been banging my head for the last 2 weeks. any help would be really appreciated. thanks in advance.
this is my first post here. this is my jsf datatable:
<h:dataTable value="#{careNeedBean.controlledCareNeedsList}" var="careNeed"
id="careneed_table" binding="#{careNeedBean.dataTable}">
<h:column>
<f:facet name="header">
<h:outputText value="NeedsLevel"/>
</f:facet>
<h:selectOneMenu id="needs_level_combo" style="width:200px;font-size:9px;"
onchange="submit()"
valueChangeListener="#{careNeedBean.saveTaskAsessment}"
binding="#{careNeedBean.selectOneMenu}">
<f:selectItem itemValue="not_assessed" itemLabel="----Not assessed----"/>
<f:selectItems value="#{careNeed.humanReadableNeedsList}" />
</h:selectOneMenu>
</h:column>
This is my bean code:
public String saveTaskAsessment(ValueChangeEvent event) {
//does some things
return "Success";
}
The valueChangeListener doesn't run on the recently changed component only. In fact, you're using JavaScript submit() function to submit the entire form. The valueChangeListener will always be executed whenever the new selected value differs from the old value as is been declared in the value attribute.
You don't have declared a value attribute, so its default value is effectively null. If the default selected item of the list is not null, then the valueChangeListener will be invoked.
To fix this, you need to assign a value attribute to the component
<h:selectOneMenu value="#{careNeed.needsLevel}">
and you need to prefill it with the same value as the default value of the dropdown list.
this.needsLevel = "not_assessed";
Alternatively, you can also make the default value null.
<f:selectItem itemValue="${null}" itemLabel="----Not assessed----"/>
Unrelated to the problem, since you're already on JSF 2.0, I'd suggest to use <f:ajax> to submit only the recently changed dropdown by ajaxical powers instead of using onchange="submit()" to submit the entire form. That's after all better for user experience.
<h:selectOneMenu>
<f:ajax />
</h:selectOneMenu>
Also, the valueChangeListener method doesn't need to return anything. It will be ignored anyway. Just declare it void.
You can use AjaxSingle="true" and onsubmit="form.refresh();" on your ajax request.
So that it will process only the current component.
form.refresh(); will remove the old cache value.
You will get the refreshed bean value.

Resources