By default, JSF generates unusable IDs, which are incompatible with the CSS part of web standards
Asked Answered
T

1

10

Can someone who is an active JSF (or Primefaces) user explain why by default this happens why nobody is doing anything about it:

<p:commandLink id="baz" update=":foo:boop" value="Example" />

Which generates markup that cannot be used in JavaScript or CSS without hacks and should generally be considered invalid:

<a href="javascript:void(0);" id=":foo:bar:baz">Example</a>

The id=":bar:baz:foo" attribute here contains colons, which aren't a valid character for this attribute, at least from CSS perspective.

While the attribute may be valid according to spec, it fails to work with real-world JavaScript and CSS implementations.

In short, default id attribute generation in JSF is unusable for front-end development.

Tattan answered 23/5, 2012 at 19:35 Comment(0)
O
32

The : is been chosen because that's the only sensible separator character for which can be guaranteed that the enduser won't accidently use it in JSF component IDs (which is been validated) and that it's possible to use it in CSS selectors by escaping it with \.

Note that the HTML4 spec says that the colon is a valid value in id and name attribute. So your complaint that it isn't compatible with "web standards" goes nowhere.

ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").

The only problem is thus that the : is a special character in CSS selectors which needs to be escaped. JS has at its own no problems with colons. The document.getElementById("foo:bar") works perfectly fine. The only possible problem is in jQuery because it uses CSS selector syntax.

If you really need to, then you can always change the default separator character : by setting the javax.faces.SEPARATOR_CHAR context param to e.g. - or _ as below. You only need to guarantee that you don't use that character anywhere in JSF component IDs yourself (it's not been validated!).

<context-param>
    <param-name>javax.faces.SEPARATOR_CHAR</param-name>
    <param-value>-</param-value>
</context-param>

The _ has by the way the additional disadvantage that it occurs in JSF autogenerated IDs like j_id1, thus you should also ensure that all NamingContainer components throughout your JSF pages have a fixed ID instead of an autogenerated one. Otherwise JSF will have problems finding naming container children.

I would only not recommend it. It's in long term confusing and brittle. To think about it again, unique elements in the average JSF webapp are by itself usually already not inside forms or tables. They generally just represent the main layout aspects. I'd say, it's otherwise a bad design in general HTML/CSS perspective. Just select them by reusable CSS class names instead of IDs. If you really need to, you can always wrap it in a plain HTML <div> or <span> whose ID won't be prepended by JSF.

See also:

Ossification answered 23/5, 2012 at 19:44 Comment(16)
@Daniel: That's specific to JS. The \ is in turn an escape character in JS strings, so you need to double-escape it.Ossification
Have you heard of pseudo classes, like :hover and :active? How would those be possible if your quote in fact describes id="" attribute permitted characters?Tattan
I verified that w3.org/TR/html401/types.html#type-name spec does, in fact, list colon as a valid character. This does not solve the problem of not being able to reference ids like that in CSS. Current a-grade browser implementations seem to treat everything after first colon as pseudo-selector that simply gets ignored, therefore entire selector is unapplied.Tattan
You should then read the CSS spec how to deal with special characters like colons and periods in CSS selectors. You need to escape them by \. Why the HTML and CSS "standards" are not in sync is a different question which is totally unrelated to JSF.Ossification
Which turns JSF templating into an awful authoring enviroment for developers. How was this not considered when you were choosing defaults?Tattan
Also, see w3.org/TR/CSS21/syndata.html#value-def-identifier which prohibits usage of colons for selectors. So in other words, with its default settings, JSF is unusable for CSS developers.Tattan
It's workable. I have by myself almost never had the need to explicitly escape them. Perhaps it's just the design that classnames are been used instead of ids to select elements. ID selectors are almost exclusively used for important layout elements like header, leftmenu, etc which are by itself of course not in forms or tables. If it really bothers you, you can always just change the javax.faces.SEPARATOR_CHAR.Ossification
I've had that changed since day one. Problem is that the default value is unusable for frontend developers. Don't even try to agrue on this one, because having to escape EVERY selector in CSS is unacceptable. If you insist on arguing the opposite, then it confirms that you represent a group of people that never consider frontend developers a priority.Tattan
I suggest to take a look at for example PrimeFaces. It uses jQuery UI under the covers. All elements are selected and styled by classnames. No pain. I myself put more question marks around the approach of defining CSS ID selectors for every single element which is by itself inside a form or table (that's when JSF will prepend the ID with the ID of the parent component and the separator character). More than often that's the case of "God Form" (a single <form> for the entire page) which is at its turn bad design, JSF or not.Ossification
You're right, there is the magic styleClass attribute, that allows adding CSS classes, making front-end development somewhat better. IDs and classes have completely different use cases, especially from performance perspective. Not having a usable id= attribute is bad and should have been a high-priority issue.Tattan
15 years ago I'd agree you on performance aspect. But these days? Again, just set javax.faces.SEPARATOR_CHAR if you like micro-optimization.Ossification
This particular issue is among many that JSF/Primefaces stack is suffering from, and as a result, it cannot compete as an authoring enviroment for front-end development.Tattan
Then just choose another one :)Ossification
Not having usable ID attributes out of the box is terribly unattractive for front-end developers. This is a problem and should be treated as such. If you're curious, I would never choose JSF stack for my own apps.Tattan
You like to keep repeating this :) I'll repeat myself as well: I've never had serious problems with this. Unique elements in my average JSF webapp are by itself never inside forms or tables. They just represent the main layout aspects. I'd say, it's otherwise a bad design in general HTML/CSS perspective.Ossification
@AndrewKolesnikov, I think you should go with that because you might be contributing JSF UI development of some other's work. Having said that one can use JQuery/ExtJS or someother JS libraries.Unready

© 2022 - 2024 — McMap. All rights reserved.