简体   繁体   中英

JSF selectOneMenu: validation of two dropdown menus

in my .jsp I have two selectOneMenu items which give me the start/end year. Now I want to display an error message if the choosen start year is bigger than the end year. How can I solve this?

<h:selectOneMenu id="minYear" value="#{statistics.minYear}" style="width: 75px">
    <f:selectItems value="#{statistics.yearValues}" />
</h:selectOneMenu>

<h:selectOneMenu id="maxYear" value="#{statistics.maxYear}" style="width: 75px">
    <f:selectItems  value="#{statistics.yearValues}"/>
</h:selectOneMenu>

In my backing bean I have a method that returns true/false if the range is valid or not.

public boolean isYearValid() {
    return (getMaxYear() >= getMinYear());
}

Normal validation in JSF can validate only single elements, so you need to circumvent this restriction. There are at least two ways to do cross-field validation with JSF.

  1. You can aply a validator to the last element (or a hidden element behind the last) define a custom validator/method, lookup the elements and do the validation.

  2. Register a listener for the PostValidateEvent like this: <f:event type="postValidate" listener="#{myValidationBean.validateDates}"/> . The rest of the procedure is exactly like in 1.

Element lookup in the validation method:

UIComponent source = event.getComponent();
UIInput minInput = (UIInput) source.findComponent("minYear");
UIInput maxInput = (UIInput) source.findComponent("maxYear");

access the values of the elements:

int minYear = ((Integer)minInput.getLocalValue()).intValue();
int maxYear = ((Integer)maxInput.getLocalValue()).intValue();

EDIT : Oops, forgot the validation message part.

String valMsg = "maxYear cannot be less than minYear";
FacesContext.getCurrentInstance().addMessage(source.getClientId(), new FacesMessage(valMsg, valMsg));

EDIT2: if you validate using the event listener and the validation fails, it is a good idea to proceed to the response rendering phase immediately to avoid invalid data to be set on the models. To do this, call context.renderResponse(); after dispatching the error message.

EDIT3: While system events have been introduced with JSF2, the first approach should be feasible with JSF 1.x. The details are slightly different at lookup and and at message dispatch as you get the context and the component passed to your validation method by JSF.

public void validateMulti(FacesContext context, UIComponent component, Object value){
  ...
  UIInput minInput = (UIInput) component.findComponent("minYear");
  ...
  context.addMessage("minYear", new FacesMessage(valMsg, valMsg));
  ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM