Reputation: 117
I'm trying to create a custom component to extend PrimeFaces.
I have a simple component called textInput under the test namespace that simply calls the PrimeFaces textInput component and prints out the value passed to an attribute named fieldClass and the names of any attributes passed
if I pass fieldClass as a string:
<test:textInput id="foo" fieldClass="field-foo" />
this is the result
fieldClass = field-foo
[com.sun.faces.facelets.MARK_ID, fieldClass]
If I pass fieldClass as an expression
<ui:param name="bar" value="field-foo"/>
<test:textInput id="foo" fieldClass="#{bar}" />
fieldClass vanishes
fieldClass = NONE
[com.sun.faces.facelets.MARK_ID]
How do I actually get hold of the attributes passed to the component?
Classes used by the custom component follows:
package test.components;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import org.primefaces.component.inputtext.*;
@FacesRenderer(
componentFamily=ExtendInputText.COMPONENT_FAMILY,
rendererType=ExtendInputTextRenderer.RENDERER_TYPE
)
public class ExtendInputTextRenderer extends InputTextRenderer {
public static final String RENDERER_TYPE = "com.example.ExtendInputTextRenderer";
@Override
public void encodeEnd(FacesContext context, UIComponent component)
throws java.io.IOException {
ResponseWriter writer = context.getResponseWriter();
Map attrs = component.getAttributes();
String fieldClass = attrs.containsKey("fieldClass") ? (String) attrs.get("fieldClass").toString() : "NONE";
writer.write("fieldClass = " + fieldClass + "<br/>");
writer.write(attrs.keySet().toString() + "<br/>");
super.encodeEnd(context, component);
}
}
package test.components;
import javax.faces.component.FacesComponent;
import org.primefaces.component.inputtext.InputText;
@FacesComponent(ExtendInputText.COMPONENT_TYPE)
public class ExtendInputText extends InputText {
public static final String COMPONENT_FAMILY = "com.example";
public static final String COMPONENT_TYPE = "com.example.ExtendInputText";
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
@Override
public String getRendererType() {
return ExtendInputTextRenderer.RENDERER_TYPE;
}
}
Upvotes: 3
Views: 4349
Reputation: 1109635
String fieldClass = attrs.containsKey("fieldClass") ? (String) attrs.get("fieldClass").toString() : "NONE";
Your mistake is that you're using containsKey()
to check if the property has been specified.
Here's an extract from UIComponent#getAttributes()
javadoc:
getAttributes
public abstract java.util.Map<java.lang.String,java.lang.Object> getAttributes()
Return a mutable
Map
representing the attributes (and properties, see below) associated wth thisUIComponent
, keyed by attribute name (which must be aString
). The returned implementation must support all of the standard and optionalMap
methods, plus support the following additional requirements:
- The
Map
implementation must implement thejava.io.Serializable
interface.- Any attempt to add a
null
key or value must throw aNullPointerException
.- Any attempt to add a key that is not a
String
must throw aClassCastException
.- If the attribute name specified as a key matches a property of this
UIComponent
's implementation class, the following methods will have special behavior:
containsKey()
- Returnfalse
.get()
- If the property is readable, call the getter method and return the returned value (wrapping primitive values in their corresponding wrapper classes); otherwise throwIllegalArgumentException
.put()
- If the property is writeable, call the setter method to set the corresponding value (unwrapping primitive values in their corresponding wrapper classes). If the property is not writeable, or an attempt is made to set a property of primitive type tonull
, throwIllegalArgumentException
.remove()
- ThrowIllegalArgumentException
.
Note that it thus always returns false
for containsKey
for component's properties. That's because dynamic properties are not stored in the attribute map, but instead in the component instance itself. They're only resolved when calling get()
.
You need to change the wrong line as follows:
String fieldClass = (String) attrs.get("fieldClass");
if (fieldClass == null) fieldClass = "NONE";
Upvotes: 3