Styling Invalid Input Fields with JSF

Have you ever tried to add a different background color like red to highlight invalid input fields when validation fails? With JSF 2.0, this is a trivial process, here is one way;

    .ui-input-invalid {
        background-color:red
    }
    <h:inputText value="#{bean.property}" required="true" styleClass="#{not component.valid ? 'ui-input-invalid' : ''}" />

component refers to the current component being rendered and if input is not valid style class applied is defined based on this condition.

There is still room for improvement, downside of the example above is as page author you need to add this condition EL to every input on the application which is a cumbersome task. Luckily with JSF 2.0 you don’t need to repeat yourself much. Here is a Component system event listener that does this behind the scenes;

package org.primefaces.examples.event;

import javax.faces.component.UIInput;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ListenerFor;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;

/**
 * @author optimus prime
 */
public class PostValidationListener implements SystemEventListener {

    public boolean isListenerForSource(Object source) {
        return true;
    }

    public void processEvent(SystemEvent event) throws AbortProcessingException {
        UIInput source = (UIInput) event.getSource();

        if(!source.isValid()) {
            source.getAttributes().put("styleClass", "ui-input-invalid");
        }
    }
}

Next step is to define this listener, for some reason probably a mojarra bug adding;

@ListenerFor(sourceClass=javax.faces.component.html.HtmlInputText.class, systemEventClass=javax.faces.event.PostValidateEvent.class)

Doesn’t work so same thing with faces-config.xml inside application tag;

<system-event-listener>
     <source-class>javax.faces.component.html.HtmlInputText</source-class>
     <system-event-class>javax.faces.event.PostValidateEvent</system-event-class>
      <system-event-listener-class>org.primefaces.examples.event.PostValidationListener</system-event-listener-class>
</system-event-listener>

That’s it, now the repetitive part can be removed from page definition, written as below and provide the same outcome;

    <h:inputText value="#{bean.property}" required="true"  />
About these ads

24 Responses to Styling Invalid Input Fields with JSF

  1. Anton says:

    wooooow! Perfect! Very cool feature, the same as the “LabelHandler” feature, which you showed a time ago! :) That was a headache in jsf 1.2 and I really didn’t realise, how to enhance this in jsf 2.0. Will steel the code, if you don’t mind )))

  2. Oleg says:

    Hello Cagatay,

    JSF 2 rocks :-)

    I think we have to rescue the original style classes (styles) at first and then restore them if the component is valid again. It can happen for view scoped beans e.g. if you put valid values after failed validation and send the request again. Something like:

    if(!source.isValid()) {
    String os = source.getAttributes().get("styleClass");
    source.getAttributes().put("ORIG_STYLE_SET", os);
    source.getAttributes().put("styleClass", os + " ui-input-invalid");
    } else {
    String os = source.getAttributes().get(ORIG_STYLE_SET);
    source.getAttributes().put("styleClass", os);
    }

    We did similar thing with JSF 1.x in a phase listener (but more complex because it must be programmed thread safe).

    Cheers. Oleg.

  3. Jardel says:

    It did not work, any special configuration besides the above mentioned?

  4. siva says:

    Can we alter this technique to highlight a field when it is selected, if so how?

  5. Venu says:

    Cool, thanks for the sharing.

  6. FreePalestine says:

    Very handy indeed!
    Thanks for sharing Cagatay :)

  7. Manuel Palacio says:

    Nice tip, thanks!

  8. rodakr says:

    very nice!
    I guess similare way autoupdate has been implemented.

    Did you ever considere to write a book… I will buy it, I’m shure not only me.

  9. Paladin says:

    “There is still room for improvement, downside of the example above is as page author you need to add this condition EL to every input on the application which is a cumbersome task”

    you also can use composite componets in this situation.

    Great post.

  10. Oleg says:

    Hi Paladin,

    I think, composite component is not an ideal solution because every inputText is a NamingContainer then and that should be consider in process / execute / update / render attributes. Cagatay’s solution is much better and cleaner.

    I can imagine how many other tricks we could implement yet with SystemEventListener :-)

  11. farouk says:

    How to find previous posts on this blog. Sometimes we want to find old articles but can’t find an easy way to do that. can you add an index or something similar?

  12. There is a search option on top right, doesn’t it work well?

  13. Paladin says:

    Hi Oleg,

    I agree with you but i have inputs with diferent behaviours in my app and i handle that with an attribute called ‘type’ in my composite, how would you do that with system event? another example is when my input have the ‘required’ atribute set to true i render a red star.

    I will take a look deeper in SystemEvent cause its new to me, see you.

  14. raphael says:

    thxalot cagatay for this classy solution
    i was facing the same problem some weeks ago and wrote a phase listener for coloring the input fields, but your approach rockz definitely more :)

    @Jardel:
    if you’re using myfaces: there is at the moment a myfaces bug with system events. subscribe your event listener to the superclass UIComponent and call instanceof in the isListenerFor… method

  15. farouk says:

    That is only useful if you are looking for something specific but if you just want to browse around looking for interesting articles you may have mised, its quite difficult

  16. Ronald van Kuijk says:

    What about wrapping something like this in a tag like in seam?

    Country:

    Zip code:

  17. Ronald van Kuijk says:

    Oops, sorry. Tags swallowed:

    [s:validateAll]

    [div]
    Country:
    [h:inputText value="#{location.country}" required="true"/]
    [/div]

    [div]
    Zip code:
    [h:inputText value="#{location.zip}" required="true"/]
    [/div>

    [h:commandButton/]

    [/s:validateAll]

  18. p:inputText applies the theme aware ui-state-error style class if it is invalid.

  19. Oleg says:

    Hi Cagatay,

    I have found today an interesting explanation why @ListenerFor doesn’t work. It’s not a Mojarra bug. It works as designed. I think, it will be ineteresting for you too. Quote:

    “You cannot use the @ListenerFor annotation to hook into SystemEvents from a UIComponent. This is because UIComponent implements ComponentSystemEventListener, and @ListenerFor is designed to ignore the SystemEventListener interface for any class that implements ComponentSystemEventListener.”

  20. I just fixed the MyFaces related issue, see https://issues.apache.org/jira/browse/MYFACES-3109 for details.

    This should work now also with MyFaces when using 2.0.6-SNAPSHOT!

  21. vbose says:

    This styling does not work with invalid field. The style is put on the span id around the input field which does not have any effect. Any work around?

  22. vbose says:

    I mean the styling does not work with p:password invalid value.

  23. vbose says:

    I mean the styling does not work with p:password invalid field value. Any work around?

  24. vitor says:

    hello cagatay…
    thank you for share this solution…

    in my application, this solution is not work correctly for primefaces components(p:inputmask or p:autocomplete, for example). InputMask extends HtmlInputText(class in the listener)…

    i’m using mojarra 2.0.3, primefaces 2.2.1, Tomcat 7 e Spring

Follow

Get every new post delivered to your Inbox.

Join 106 other followers

%d bloggers like this: