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

Ikthiander picture Ikthiander · Jan 20, 2011 · Viewed 8.9k times · Source

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";
} 

Answer

BalusC picture BalusC · Jan 20, 2011

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.