jsf - Styling UIInputs that fail validation -


the problem

i'm trying work form validation in jsf 1.2. have form rows of 2 input text fields.

i enter 2 rows of data, 1 bad cell, this:

| :) | :/ | | :) | :) | 

the validator called once each row, checks both fields. each uiinput fails validation added list of failed uicomponents. method submit action gets run. first restores saved styles. loops on failed uicomponents. inside loop, saves current style, sets style "badinput".

but when page loads, both end-cells have "badinput" style:

| :) | :/ | | :) | :/ | 

my code

this validator, method on managed bean handles page:

public void validatetime(facescontext context, uicomponent component, object value) {   uiinput out = (uiinput) component.findcomponent("out");    (uicomponent uic : arrays.aslist(component, out))   {     string time = (string) ((uiinput)uic).getsubmittedvalue();      if (!stringtotime.isvalid(time))     {       // mark found invalid times       validtimes = false;        // save failed component       // click method change style during render phase       faileduics.add(uic);  // list<uicomponent>       badcomps.put(uic.getclientid(context), uic);  // map<string, uicomponent>     }   } } 

and here's table of input fields:

<h:datatable binding="#{entryhandler.tableattends}" value="#{entryhandler.attends}" var="range">   <h:column>     <div>       <h:outputlabel>         <h:outputtext value="in: " />         <h:inputtext value="#{range.start}" id="in" validator="#{entryhandler.validatetime}" />       </h:outputlabel>        <h:outputlabel>         <h:outputtext value="out: " />         <h:inputtext value="#{range.end}" id="out" />       </h:outputlabel>        <h:commandlink action="#{entryhandler.delattend}" value="x" styleclass="removetime" />     </div>   </h:column> </h:datatable> 

i've tried applying bad input style these 2 ways:

for (uicomponent target : faileduics) {   log.debug("target client id: " + target.getclientid(context));    map<string, object> attr = target.getattributes();    // save style before changing   string style = (string) attr.get("styleclass");   originalstyle.put(target.getclientid(context), style);    // add badinput css class   if (style == null) style = "";   attr.put("styleclass", "badinput " + style); } faileduics = new arraylist<uicomponent>(); 

and second:

uicomponent root = context.getviewroot(); (string clientid : badcomps.keyset()) {   root.invokeoncomponent(context, clientid, new badinputcallback(originalstyle)); } badcomps = new hashmap<string, uicomponent>(); 

where callback function:

private static class badinputcallback implements contextcallback {   private final map<string, string> originalstyle;    public badinputcallback(map<string, string> originalstyle)   {     this.originalstyle = originalstyle;   }    @override   public void invokecontextcallback(facescontext context, uicomponent target)   {     map<string, object> attr = uic.getattributes();      // save style before changing     string style = (string) attr.get("styleclass");     originalstyle.put(target.getclientid(context), style);      // add badinput css class     if (style == null) style = "";     attr.put("styleclass", "badinput " + style);   } } 

your concrete problem caused because there physically only one input component in component tree, state changes whenever parent uidata component iterates on every item of model. when want set styleclass dynamically, need let depend on iterated item, so:

<h:datatable ... var="item">     <h:column>         <h:inputtext ... styleclass="#{item.bad ? 'badinput' : ''}" />     </h:column> </h:datatable> 

or when you're on jsf 2.x, check uiinput#isvalid() instead whereby uiinput referenced via implicit el variable #{component}, so:

<h:datatable ... var="item">     <h:column>         <h:inputtext ... styleclass="#{component.valid ? '' : 'badinput'}" />     </h:column> </h:datatable> 

this problem identified before , taken account in among others jsf 1.2 targeted setfocuslistener phase listener on balusc code , jsf 2.0 <o:highlight> component of jsf utility library omnifaces.

both have under covers same approach: collect client ids of invalidated input components , pass them array javascript code in turn sets desired class name via html dom.

see also:


Comments

Popular posts from this blog

image - ClassNotFoundException when add a prebuilt apk into system.img in android -

I need to import mysql 5.1 to 5.5? -

Java, Hibernate, MySQL - store UTC date-time -