Custom HTML Tag Attributes Are Not Rendered by Jsf

Custom HTML tag attributes are not rendered by JSF

This is by design. You can only specify attributes which are supported by the JSF component itself (i.e. it's listed in the attribute list in the tag documentation). You can't specify arbitrary additional attributes, they will all be plain ignored.

There are several ways to solve this:

  1. If you're already on JSF 2.2+, simply specify it as passthrough attribute:

    <html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
    ...
    <h:inputText ... a:autocorrect="off" />

    (note that I'm using xmlns:a instead of xmlns:p to avoid clash with PrimeFaces default namespace)

    Or:

    <html ... xmlns:f="http://xmlns.jcp.org/jsf/core">
    ...
    <h:inputText ...>
    <f:passThroughAttribute name="autocorrect" value="off" />
    </h:inputText>

  2. Create a custom renderer. You can find several concrete examples in below answers:

    • How to let JSF pass through HTML attributes
    • Using bootstrap related tags inside JSF2 h:inputText component
    • How to render a custom attribute of <h:outputLink>?
    • InputText PrimeFaces not applying maxlength
    • Adding Custom Attributes to Primefaces Autocomplete Component in JSF

JSF removes custom HTML component attributes

You don't need to write your own tags, it is sufficient to write your own renderer for the JSF-tags. A renderer which does not omit your custom attributes.

Look here on how to write & configure such a renderer for all your inputs.

Have JSF tag NOT render an HTML tag

The <span> is only generated if you give the <h:panelGroup> an attribute which must end up in HTML, such as id, styleClass, etc. In your given example, the <h:panelGroup> has only a rendered attribute, so nothing will be generated to the HTML.

So, to achieve your requirement, just remove all attributes other than rendered from the <h:panelGroup>, exactly as you did in your own question example.

JSF 2.0 strips out needed HTML5 attributes

JSF isn't exactly stripping them out. It's just ignoring them because they are not among the supported/known attributes of the component in question. In case of for example <h:inputText> (which renders by default a HTML <input type="text"> tag), you can find all supported attributes in the view declaration language (VDL) documentation.

To overcome this, you would need to create a custom component or, better, just a custom renderer which overrides the standard <h:inputText> renderer and takes the custom attributes into account.

How to let JSF pass through HTML attributes

JSF by design ignores all custom attributes when rendering HTML.

If you're already on JSF 2.2+, simply specify it as passthrough attribute:

<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<p:autoComplete a:x-webkit-speech="x-webkit-speech" ... />

If you're not on JSF 2.2 yet, then you need a custom renderer. This is in case of PrimeFaces <p:autoComplete> (and all other components) fortunately relatively simple. It's sufficient to override just the renderPassThruAttributes() method wherein you add the new attribute which you'd like to render to the attrs argument and finally delegate to the super method.

E.g.

package com.example;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import org.primefaces.component.autocomplete.AutoCompleteRenderer;

public class MyAutoCompleteRenderer extends AutoCompleteRenderer {

@Override
protected void renderPassThruAttributes(FacesContext facesContext, UIComponent component, String[] attrs) throws IOException {
String[] newAttrs = new String[attrs.length + 1];
System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
newAttrs[attrs.length] = "x-webkit-speech";
super.renderPassThruAttributes(facesContext, component, newAttrs);
}

}

To get it to run, register it as follows in your webapp's faces-config.xml:

<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.AutoCompleteRenderer</renderer-type>
<renderer-class>com.example.MyAutoCompleteRenderer</renderer-class>
</renderer>
</render-kit>

(you can find out the component family and renderer type by looking at the source code of AutoComplete class, they're specified as COMPONENT_FAMILY and RENDERER_TYPE constants in there)

No, the @FacesRenderer annotation simply won't work when the purpose is to override custom renderers which are by itselves already registered in a faces-config.xml.

Custom attributes added by a custom renderer appears at the wrong HTML elements

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.



Related Topics



Leave a reply



Submit