Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF 2.0; Validator tag "disabled" depends on value from page

In my jsf application i want to validate a field which should only be validated, when one option in a SelectOneRadio is checked.

I found out, that <f:validator> has an attribute, called "disabled".

Can i use this, to check the value from another field?

I tried, but i haven't access to the value from my bean.

<h:selectOneRadio value="#{myBean.checkedSelectOneRadioValue}">
    <f:selectItems value="#{myBean.valuesForSelectOneRadio}" />
</h:selectOneRadio>


<f:validator validatorId="myValidator" disabled="#{myBean.checkedSelectOneRadioValue == 'TEST'}" />

Is there any way to reach that without writing own validatorhandler?

Thanks!

like image 715
Tobi Avatar asked Dec 27 '22 03:12

Tobi


1 Answers

The <f:validator> is a tag handler, not an UI component. All its attributes are per definition evaluated during view build time, not during view render time. The view build time is that moment when the XHTML file is been parsed into a JSF component tree as available by context.getViewRoot(). The very same view is usually reused across postbacks to the same view by returning null/void in (ajax) actions.

So you can't let a tag handler attribute depend on a render time attribute which can change during a postback request. One of the ways is to perform that check inside the custom validator itself.

E.g.

<h:inputText>
    <f:validator validatorId="myValidator" />
    <f:attribute name="radio" value="#{myBean.checkedSelectOneRadioValue}" />
</h:inputText>

with

@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {     
    if (!"TEST".equals(component.getAttributes().get("radio"))) {
        return;
    }

    // Perform actual validation here.
}

You can alternatively also use OmniFaces <o:validator> instead. It extends the standard <f:validator> with request based evaluation of EL in attributes.

<h:inputText>
    <o:validator validatorId="myValidator" disabled="#{bean.checkedSelectOneRadioValue == 'TEST'}" />
</h:inputText>

See also the showcase example and the source code from which an extract of relevance is posted below:

@Override
public void apply(FaceletContext context, UIComponent parent) throws IOException {
    if (!ComponentHandler.isNew(parent)) {
        return;
    }

    final javax.faces.validator.Validator validator = createValidator(context);
    final RenderTimeAttributes attributes = collectRenderTimeAttributes(context, validator);
    final ValueExpression disabled = getValueExpression(context, "disabled", Boolean.class);
    ((EditableValueHolder) parent).addValidator(new javax.faces.validator.Validator() {

        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
            if (disabled == null || Boolean.FALSE.equals(disabled.getValue(context.getELContext()))) {
                attributes.invokeSetters(context.getELContext(), validator);
                validator.validate(context, component, value);
            }
        }
    });
}
like image 194
BalusC Avatar answered Jan 12 '23 14:01

BalusC