1

With JSF2, Facelets.

I need to code a CSS style based on a variable that can contain multiple (undetermined) values:

<p rendered="#{not empty element.state}" class="globalStyle CODED_CLASS_ACCORDING_TO_element.state">#{element.state}</p>

How to get CODED_CLASS_ACCORDING_TO_element.state in JSF is uncertain to me. Most of the answers I see always apply a ternary option (odd/even, on/off, applied/not_applied...) which is not valid in my case, because state can be "Done", "Under development", "initiated", etc. Neither it is to code the conversion in the bean, since it should not know about view. Is still option 3 in this answer the preferred one?

  • style="color: #{yourVar == 'yes' ? 'green' : 'red'};"
  • make two <h:outputText> components with different styles, each with a different rendered attribute (one #{yourVar == 'yes'} and the other #{yourVar == 'no'})
  • define a (jstl/facelets/jsf 2.0) function that takes the var as argument and returns a style/class - styleClass="#{my:getStyleClass(yourVar)}"

If so, I am not sure how to do this (I am entirely new to JSF). I can think of a <cc:interface> and <cc:implementation> and render the right output according to some <c:if> condition, but I am sure it is not the right way and it would bevery inneficient.

Community
  • 1
  • 1
user1156544
  • 1,725
  • 2
  • 25
  • 51

1 Answers1

1

Just make state an enum.

public enum State {
    DONE, UNDER_DEVELOPMENT, INITIATED, ETC;
}

And use it directly as class name.

<p ... class="globalStyle state #{element.state}">
.state.DONE {
    color: green;
}

.state.UNDER_DEVELOPMENT {
    color: orange;
}

.state.INITIATED {
    color: red;
}

.state.ETC {
    color: pink;
}

Using enums has other advantages too. E.g. How to use enum values in f:selectItem(s) and Localizing enum values in resource bundle.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks BalusC. Mmmm... then I would have to change the bean, which contains a String, and make the conversion when reading the database. But the main problem is that I don't have a predefined list. State is a String that can contain anything, because it comes from distributed sources that I don't control. Is there no other solution? – user1156544 Apr 05 '16 at 13:37
  • Then your best bet is print it directly as CSS class, but don't forget to strip out all illegal CSS characters (e.g. whitespace). You're only moving the problem of having non-predefined enum values to having non-predefined CSS classes. Not sure which is preferable. I think you may need to take a step back and define some business rules first. – BalusC Apr 05 '16 at 13:39
  • Yes, I thought of printing the value and remove white spaces (and illegal characters as you said), but I discarded the idea because it looks too inefficient for such a small thing. There is no replacement for an old "scriplet switch" in JSF? Otherwise I think will just create a "coding" method in the Named bean, although I dont like mixing model with view :-/ Thanks – user1156544 Apr 05 '16 at 13:45
  • Another point is that even if I managed to compile state as an ENUM, then I would print the ENUM in the HTML (i.e. "UNDER_DEVELOPMENT" instead of "Under Development") – user1156544 Apr 05 '16 at 13:47
  • Switch? The enum should eliminate exactly that! A `string.replaceAll("\\W+", "")` to get a valid CSS identifier isn't that much work. As to printing enum directly, yes that's the way of least effort and most clean code. – BalusC Apr 05 '16 at 13:48
  • You are right about the switch. I will go for the state.replaceAll('\\W+', ''). Many thanks for your help (Hopefully JSF will prevent users from doing HTML injection, since I print directly what is read from the DB) – user1156544 Apr 05 '16 at 13:58
  • JSF has builtin XSS prevention over all place, also here. See also http://stackoverflow.com/q/7722159 – BalusC Apr 05 '16 at 14:01
  • Thank you! Bedankt Gracias Grazie Danke – user1156544 Apr 05 '16 at 14:17
  • You're welcome! Graag gedaan. De nada. Prego. Bitte. – BalusC Apr 05 '16 at 14:19