I have a form in JSF2 with 2 checkboxes (<h:selectBooleanCheckbox>
). At least one of them should be checked. Both checked are also ok, but when none is checked, there should be error.
This validation should work also on ajax, i.e. when user checks/unchecks, error message should disappear/appear.
So I binded both checkboxes to UISelectBoolean
elements and added validator to each. In validator I check value of the second checkbox, if it is false, and current checkbox is also set to false, errormessage is produced. Smth like:
if (newValue == false && secondCheckbox.getValue() == false) {
throw new ValidationException();
}
Problem is when user unchecks checkbox on the page, while the other is also unchecked, this false value doesn't go to the model, nor event to UISelectBoolean.
Scenario:
- Initially both are unchecked
- User checks checkbox1.
newValue
istrue
, so this is valid, goes to UISelectBoolean and model.- User unchecks checkbox1. Checkbox2 is
false
,newValue
isfalse
, so exception is thrown. Because of failed validation, thisfalse
value doesn't go to the model, nor even to UISelectBoolean element. - User checks checkbox2.
True
value goes to the model and UISelectBoolean. - U开发者_JAVA技巧ser unchecks checkbox2. Checkbox1 is still unchecked on the page, but in the model and UISelectBoolean there is still
true
. So validation passes and there is no error message. On the page both checkboxes are unchecked, but in model checkbox1 is stilltrue
.
How to solve such a problem?
Consider <h:selectManyCheckbox required="true">
. Here's a kickoff example:
<h:form>
<h:selectManyCheckbox id="options" value="#{bean.checked}" required="true">
<f:selectItems value="#{bean.options}" />
<f:ajax render="optionsMessage" />
</h:selectManyCheckbox>
<h:message id="optionsMessage" for="options" />
<h:commandButton value="Submit" action="#{bean.submit}">
<f:ajax execute="@form" render="@form" />
</h:commandButton>
<h:messages globalOnly="true" />
</h:form>
With
@ManagedBean
@RequestScoped
public class Bean {
private List<String> checked;
private List<String> options = Arrays.asList("first", "second");
public void submit() {
System.out.println("Checked: " + checked);
}
// ...
}
The f:ajax
works fine here. Probably you've used event="click"
instead of (the default) event="valueChange"
which will cause that the checkmark won't be retained after render. The click
is namely called right before the checkmark get visually set. The render would block the checkmark being visually set.
精彩评论