Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the value of another component in a custom validator? [duplicate]

I use a custom validator. The difficulty is that I just need to check two fields inputText and compare them. The first field must be greater than the second field. If not, then I have to show a message with the error information. So I need to pass in my custom validator the value of first inputText field. To do this I need to read a value of first InputText field in my validator class. How can I get a id of necessary component in a validator class? Solution using the tag does not suit me. I need to go to the desired component is directly Maybe this can be done through any methods of the FacesContext?

like image 588
Michael Avatar asked Sep 30 '11 09:09

Michael


2 Answers

Just pass the whole component via <f:attribute>.

<h:form id="formId">
    <h:inputText value="#{bean.start}">
        <f:validator validatorId="rangeValidator" />
        <f:attribute name="endComponent" value="#{endComponent}" />
    </h:inputText>
    ...
    <h:inputText binding="#{endComponent}" value="#{bean.end}" />
    ...
</h:form>

(note: binding code is as-is, do NOT let it refer a bean property!)

with in validator

UIInput endComponent = (UIInput) component.getAttributes().get("endComponent");
Object endComponentValue = endComponent.getSubmittedValue();
// ...

Important note is that the components are processed, converted and validated in the order as they appear in the tree. Any submitted value of components which aren't converted/validated yet is available by UIInput#getSubmittedValue() and any of those which are already converted/validated is available by UIInput#getValue(). So, in your particular example, you should get the value by UIInput#getSubmittedValue() instead of UIInput#getValue().

If you'd like to work with the already converted and validated value as available by UIInput#getValue(), then you need to move the validator to the second component and then pass the first component along instead.

<h:form id="formId">
    <h:inputText binding="#{startComponent}" value="#{bean.start}" />
    ...
    <h:inputText value="#{bean.end}" />
        <f:validator validatorId="rangeValidator" />
        <f:attribute name="startComponent" value="#{startComponent}" />
    </h:inputText>
    ...
</h:form>
UIInput startComponent = (UIInput) component.getAttributes().get("startComponent");
Object startComponentValue = startComponent.getValue();
// ...

See also:

  • JSF doesn't support cross-field validation, is there a workaround?
  • Error validating two inputText fields together
  • Validator for multiple fields
like image 90
BalusC Avatar answered Nov 30 '22 08:11

BalusC


You can just grab the other field's value from the request parameter map using the input field' name attribute. To get the name attribute of the input field do a view source to see what gets generated. See example below.

public void validate(FacesContext fc, UIComponent uic, Object o) throws ValidatorException {
    String newPassword = fc.getExternalContext().getRequestParameterMap().get("centerForm:newPassword");
    String newPassword2 = (String) o;
    if(!newPassword.equals(newPassword2)){
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,"New Passwords do not match", null);            
        throw new ValidatorException(msg);            
    }
}
like image 45
Mr. Port St Joe Avatar answered Nov 30 '22 07:11

Mr. Port St Joe