A question we keep getting from users is to have selections (drop-down lists or multi-selects) with dependent values. For instance, a user would pick a country, then the system populates a city dropdown with the cities in that country.
I've made this work often enough in session (or conversation scope) but now, for a real lightweight scenario, I would like to have it work in request scope.
Here's some dummy code showing the problem (usually we would use A4J to populate the dropdowns without a full refresh, but the problem can be demonstrated with plain jsf as well):
JSF:
<h:form>
<p>
<h:selectOneMenu value="#{bean.selectedSourceValue}">
<f:selectItems value="#{bean.sourceValues}" />
</h:selectOneMenu>
</p>
<p>
<h:selectOneMenu value="#{bean.selectedDependentValue}">
<f:selectItems value="#{bean.dependentValues}" />
</h:selectOneMenu>
</p>
<p>
<h:commandButton value="submit" />
</p>
</h:form>
Backing bean:
public class Bean {
private Integer selectedSourceValue;
private Integer selectedDependentValue;
/**
* @return values for the first selection. Numbers from 1 to 10.
*/
public List<SelectItem> getSourceValues(){
List<SelectItem> r = new ArrayList<SelectItem>();
for(int i=1; i<=10; i++){
r.add(new SelectItem(i));
}
return r;
}
/**
* @return values for the second selection. First ten powers of the selected first value.
*/
public List<SelectItem> getDependentValues(){
if (selectedSourceValue==null) return Collections.emptyList();
List<SelectItem> r = new ArrayList<SelectItem>();
for(int i=1; i<=10; i++){
r.add(new SelectItem((int)Math.pow(selectedSourceValue, i)));
}
return r;
}
// ... snipped some basic getter and setters
}
Seems simple enough. The problem is when making the second selection. When the second dropdown is submitted, the combos are validated. But in the validation phase, the request-scoped bean is not populated yet, so getDependentValues()
returns null. This causes jsf to throw a NoSuchElementException
(using Sun RI).
Any idea on how to solve this, or even whether it's possible?