validation - Setting a validator attribute using EL based on ui:repeat var -
i looking little bit of guidance today issue running into.
what trying accomplish build page on fly validation , all. end result allow user configure fields on page through administrative functions. below copy of code using test page loop through "configured" fields , write out fields using defined criteria.
<ui:repeat var="field" value="#{eventmgmt.eventfields}" varstatus="status"> <div class="formlabel"> <h:outputlabel value="#{field.customname}:"></h:outputlabel> </div> <div class="forminput"> <h:inputtext id="inputfield" style="width:# {field.fieldsize gt 0 ? field.fieldsize : 140}px;"> <f:validateregex disabled="#{empty field.validationpattern}" pattern="#{field.validationpattern}"></f:validateregex> </h:inputtext> <h:message for="inputfield" showdetail="true" errorclass="errortext"></h:message> </div> </ui:repeat> after page renders , attempt submit values field, following message "regex pattern must set non-empty value." means expression not populated. makes interesting me fields not have expression them disabled when el evaluated. can take same code #{field.validationpattern} , put in page , correct value written on page.
so, question(s) are: 1. possible? 2. @ point jsf container @ binding pattern validate regex? 3. doing wrong or right way ??
i running tomcat 7.0.22, mojarra 2.1.5, , eclipse ide.
this caused using <f:validateregex> properties depend on iterated item of <ui:repeat>.
the <f:xxx> tags tag handlers, not ui components. tag handlers parsed , evaluated when ui component tree built during view build time. el evaluated during view build time. <h:xxx> tags , <ui:xxx> tags <ui:repeat> ui components. el evaluated during view render time.
so in case, when <f:validateregex> parsed , executed, #{field} not available in current el scope , evaluates null.
there several ways work.
move validator class representing
field, reference follows:<h:inputtext ... validator="#{field.validate}" />with in
fieldclass wherein manually instantiate it:public void validate(facescontext context, uicomponent component, object value) throws validatorexception { if (pattern != null) { regexvalidator regexvalidator = new regexvalidator(); regexvalidator.setpattern(pattern); regexvalidator.validate(context, component, value); } }or, wrap
#{eventmgmt.eventfields}inlistdatamodel<field>, bind validator#{eventmgmt}bean. way able set validator's properties based on row data:<h:inputtext ... validator="#{eventmgmt.validate}" />with in backing bean class behind
#{eventmgmt}:private datamodel<field> model; private regexvalidator regexvalidator; @postconstruct public void init() { regexvalidator = new regexvalidator(); } public void validate(facescontext context, uicomponent component, object value) throws validatorexception { string pattern = model.getrowdata().getpattern(); if (pattern != null) { regexvalidator.setpattern(pattern); regexvalidator.validate(context, component, value); } }or, create custom
validatorextendsregexvalidator, set pattern custom attribute of component<f:attribute>, letvalidatorintercept on that.<f:attribute>adds new attribute component unevaluatedvalueexpression, re-evaluated when call it. e.g.:<h:inputtext ...> <f:validator validatorid="extendedregexvalidator" /> <f:attribute name="pattern" value="#{field.pattern}" /> </h:inputtext>with
@facesvalidator("extendedregexvalidator") public class extendedregexvalidator extends regexvalidator { @override public void validate(facescontext context, uicomponent component, object value) throws validatorexception { string pattern = (string) component.getattributes().get("pattern"); if (pattern != null) { setpattern(pattern); super.validate(context, component, value); } } }or, if happen use jsf utility library omnifaces, use
<o:validator>. e.g.<h:inputtext ...> <o:validator validatorid="javax.faces.regularexpression" pattern="#{field.pattern}" /> </h:inputtext>yes, that's all.
<o:validator>make sure attributes evaluated deferred expressions instead of immediate expressions.
Comments
Post a Comment