I had to write a custom renderer for <h:commandLink/>
tag to support data-*
HTML5 attributes in order to use JSF 2.1 with jQuery mobile framework.
My JSF markup and the output generated by this markup are as follows:
<h:commandLink value="Prev" data-theme="e" data-role="button" data-inline="true" data-mini="true" data-icon="arrow-l"/>
<h:commandLink value="Page 1 of 3" data-theme="e" data-role="button" data-inline="true" data-mini="true"/>
<h:commandLink value="Next" data-theme="e" data-role="button" data-inline="true" data-mini="true" data-icon="arrow-r" data-iconpos="right"/>
It is obvious that my custom renderer properly renders the 2nd and the 3rd <h:commandLink/>
tags, but not the 1st one. It seems the data-*
attributes belong to the 1st tag is rendered with the immediate parent <div/>
tag. This seems a strange (and buggy) behaviour of Mojarra (I use V 2.1.11
). Please advice me how to overcome this?
My custom renderer code as follows:
public class MyCommandLinkRenderer extends CommandLinkRenderer {
@Override
public void encodeBegin(FacesContext context, UIComponent component) {
String[] attributes = {"data-theme", "data-role", "data-icon", "data-inline", "data-mini", "data-iconpos"};
ResponseWriter writer = context.getResponseWriter();
try {
for (String attribute : attributes) {
String value = (String) component.getAttributes().get(attribute);
if (value != null) {
writer.writeAttribute(attribute, value, attribute);
System.out.println(attribute + " " + value);
}
}
super.encodeBegin(context, component);
} catch (Exception e) {
}
}
}
You must call super.encodeBegin()
before writing the attributes.
Otherwise you're writing the attributes to the previous HTML element, as confirmed by the generated HTML output. The super.encodeBegin()
starts the new HTML element.
This is just a bug in your own code, not in Mojarra.
Update: also, overriding the encodeBegin()
was not right in first place. You should rather be overriding the LinkRenderer#writeCommonLinkAttributes()
method.
@Override
protected void writeCommonLinkAttributes(ResponseWriter writer, UIComponent component) throws IOException {
super.writeCommonLinkAttributes(writer, component);
// ...
}
It does by the way then not matter if you call super
before or after your job.