duminică, 7 iunie 2015

[OmniFaces utilities 2.0] Write component attributes of the given property-HTML mapping of names


[OmniFaces utilities] The writeAttributes() method writes component attributes of the given property-HTML mapping of names, if it's not empty. Map key will be used as component property name and map value will be used as HTML attribute name.

Method:
Usage:

A practical case of Renderers#writeAttributes() occurs when we write a custom component that extends an existing component and inherits its attributes. More precisely, we want to strictly refer to the mapping of component property-HTML attribute names of the attributes to be written (e.g. property-HTML mapping of names listed in HtmlGraphicImage, HtmlInputText, HtmlOutputText, etc). At rendering phase of our custom component we have two alternatives:

·         nominate each HTML attribute name and invoke the UIComponent#getAttributes()#get(component_property_name)
·         collect the mapping of component property-HTML attribute names of the attributes to be written in a Map and invoke Renderers#writeAttributes()

The first approach is a little bit clumsy. But, if we rely on the fact that JSF list the mapping of component property-HTML attribute names of the attributes to be written in a protected Java enum named, PropertyKeys, (see javax.faces.component.html classes) then we can write a snippet of code capable to collect this mapping for any JSF component, like this:

import org.omnifaces.util.Renderers;
...
public class MyComponent extends HtmlGraphicImage {
public class MyComponent extends HtmlOutputText {
public class MyComponent extends HtmlInputText {
...
public static final Map<String, String> ATTRIBUTE_NAMES = collectAttributeNames();

private static Map<String, String> collectAttributeNames() {
 Map<String, String> attributeNames = new HashMap<>();
 for (PropertyKeys propertyKey : PropertyKeys.values()) {
      String name = propertyKey.name();
      // 'class' is the HTML equivalent of 'styleClass'; since 'class' is a reserved
      // Java keyword it cannot appear in the enum.
      attributeNames.put(name, "styleClass".equals(name) ?
                               "class" : propertyKey.toString());
 }

 return Collections.unmodifiableMap(attributeNames);
}

Further, in a method specific to rendering (e.g. encodeBegin()), we can render the mapping, like below:

@Override
public void encodeBegin(FacesContext context) throws IOException {
 ResponseWriter writer = context.getResponseWriter();
 ...
 writeAttributes(writer, this, MyComponent.ATTRIBUTE_NAMES);
}

Niciun comentariu:

Trimiteți un comentariu