我正在构建自定义 JSF 复合组件,以便输入周期。我有这个模型:
public class Periodicity implements Serializable {
private PeriodicityType type;
private Integer value = 0;
public PeriodicityExchange() {
super();
}
/**Getter and setters**/
}
其中PeriodicityType
是一个包含DAY
、WEEK
、MONTH
、YEAR
的枚举>.
该模型的输入组件由 p:spinner
组成。元素用于选择数值,h:selectOneMenu
用于选择周期类型。该组件运行良好,但现在我想要一个 java 类支持它,所以我修改了我的 Facelet 文件:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:composite="http://xmlns.jcp.org/jsf/composite"
xmlns:p="http://primefaces.org/ui">
<composite:interface componentType="periodicityInput">
<composite:attribute name="value" type="model.Periodicity" />
</composite:interface>
<composite:implementation>
<div class="col-xs-2">
<p:spinner binding="#{cc.periodicityValue}"
value="#{cc.attrs.value.value}" min="0" />
</div>
<div class="col-xs-3">
<h:selectOneMenu binding="#{cc.periodicityType}"
value="#{cc.attrs.value.type}" styleClass="form-control">
<f:selectItem itemLabel="No periodicity" noSelectionOption="true" />
<f:selectItem itemLabel="Days" itemValue="DAY" />
<f:selectItem itemLabel="Weeks" itemValue="WEEK" />
<f:selectItem itemLabel="Months" itemValue="MONTH" />
<f:selectItem itemLabel="Years" itemValue="YEAR" />
</h:selectOneMenu>
</div>
</composite:implementation>
</html>
这是我的 java 类(基于 this BalusC's tutorial )。它使用 faces-config.xml 文件注册为组件:
public class PeriodicityInput extends UIInput implements NamingContainer {
private UIInput periodicityValue;
private UIInput periodicityType;
@Override
public void encodeBegin(FacesContext context) throws IOException {
super.encodeBegin(context);
}
@Override
protected Object getConvertedValue(FacesContext context, Object newSubmittedValue)
throws ConverterException {
try {
return new PeriodicityExchange(
Integer.parseInt(newSubmittedValue.toString().split("-")[0]),
newSubmittedValue.toString().split("-")[1]);
} catch (Exception ex) {
throw new ConverterException(ex);
}
}
public String getFamily() {
return COMPONENT_FAMILY;
}
public UIInput getPeriodicityType() {
return periodicityType;
}
public UIInput getPeriodicityValue() {
return periodicityValue;
}
@Override
public Object getSubmittedValue() {
return periodicityValue.getSubmittedValue() + "-" + periodicityType.getSubmittedValue();
}
public void setPeriodicityType(UIInput periodicityType) {
this.periodicityType = periodicityType;
}
public void setPeriodicityValue(UIInput periodicityValue) {
this.periodicityValue = periodicityValue;
}
}
问题是,一旦我使用 componentType
属性将我的组件绑定(bind)到 java 类,该组件就会停止渲染。 encodeBegin
被调用,但进行了一些进一步的调试,我注意到当 JSF 尝试获取复合组件的渲染器时,它返回 null。 UIComponentBase
类中的方法 getRenderer(FacesContext)
尝试访问 context.getRenderKit().getRenderer(getFamily(), rendererType)
,其中该系列的计算结果为 javax.faces.Input
,rendererType
为 javax.faces.Composite
。
我正在使用 Mojarra 2.2.12。我在这里缺少什么?
最佳答案
where the family evaluates to
javax.faces.Input
这是不正确的。它应该是 javax.faces.NamingContainer
,即 UINamingContainer.COMPONENT_FAMILY
的常量值。 .
下面的 COMPONENT_FAMILY
在使用静态导入进行重构期间可能会出现困惑:
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
上面实际上继承自UIInput
,但它必须是UINamingContainer
。最好用 FQN 指定。
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
关于JSF 无法获取自定义复合输入组件的渲染器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39367862/