将属性值传递给标准组件
我们先看一下标签描述文件(TLD)中定义的 Value Scroller 提供的属性。
清单 3. 在 TLD 中定义自定义复合组件的属性
<tag>
<name>valueScroller</name>
<tag-class>component.taglib.ValueScrollerTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>id</name>
<description>ValueScroller ID</description>
</attribute>
<attribute>
<name>value</name>
<description>ValueScroller value</description>
</attribute>
<attribute>
<name>size</name>
<description>Input field size</description>
</attribute>
<attribute>
<name>min</name>
<description>Minimum value</description>
</attribute>
<attribute>
<name>max</name>
<description>Maximum value</description>
</attribute>
<attribute>
<name>step</name>
<description>Scrolling step</description>
</attribute>
</tag>
<name>valueScroller</name>
<tag-class>component.taglib.ValueScrollerTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>id</name>
<description>ValueScroller ID</description>
</attribute>
<attribute>
<name>value</name>
<description>ValueScroller value</description>
</attribute>
<attribute>
<name>size</name>
<description>Input field size</description>
</attribute>
<attribute>
<name>min</name>
<description>Minimum value</description>
</attribute>
<attribute>
<name>max</name>
<description>Maximum value</description>
</attribute>
<attribute>
<name>step</name>
<description>Scrolling step</description>
</attribute>
</tag>
我们看到,除了 min/max/step 是自定义的属性之外,其他的都属于 JSF 标准组件的属性,可以直接传递给构成 Value Scroller 的标准组件处理,完全不用为这些标准组件的属性覆盖实现方法 saveState() 和 restoreState() 。
通常有两种方法传递属性值。当你需要对属性进行一些额外的操作(如验证或者转换等),可以在标签类 ValueScrollerTag 中将属性传递给自定义组件类,如下所示:
清单 4. 传递自定义属性
/**
* Override the setProperties method
*/
protected void setProperties(UIComponent component) {
super.setProperties(component);
ValueScroller vs = (ValueScroller)component;
Application app = FacesContext.getCurrentInstance().getApplication();
// Set value attribute
if (value != null) {
if (isValueReference((String)value)) {
ValueBinding vb = app.createValueBinding((String)value);
vs.setValueBinding("value", vb);
} else {
throw new IllegalArgumentException("The value property must be a value " +
"binding expression that points to a bean property.");
}
}
// Set id attribute
if (id != null) {
vs.setId((String)id);
}
// Set other attributes
vs.setMin(min);
vs.setMax(max);
vs.setStep(step);
}
* Override the setProperties method
*/
protected void setProperties(UIComponent component) {
super.setProperties(component);
ValueScroller vs = (ValueScroller)component;
Application app = FacesContext.getCurrentInstance().getApplication();
// Set value attribute
if (value != null) {
if (isValueReference((String)value)) {
ValueBinding vb = app.createValueBinding((String)value);
vs.setValueBinding("value", vb);
} else {
throw new IllegalArgumentException("The value property must be a value " +
"binding expression that points to a bean property.");
}
}
// Set id attribute
if (id != null) {
vs.setId((String)id);
}
// Set other attributes
vs.setMin(min);
vs.setMax(max);
vs.setStep(step);
}
另外一种方法就是在标签类 ValueScrollerTag 中直接把属性值加入相应标准组件的属性 Map 。例如,将 size 属性传递给自定义复合组件包含的 UIInput:
清单 5. 传递标准属性
vs.findComponent("input").getAttributes().put("size", new Integer(size));