在数据表的列中使用不同的(以编程方式创建的)JSF组件
对于JSF页面,我有以下在数据表的列中使用不同的(以编程方式创建的)JSF组件,jsf,jsf-2,Jsf,Jsf 2,对于JSF页面,我有以下xhtml代码: <h:dataTable value="#{bean.data}" var="elem"> <h:column> <h:panelGroup binding="#{elem.displayComponent}"/> </h:column> </h:dataTable> 一种实现可能是: public class LabelElement implements C
xhtml
代码:
<h:dataTable value="#{bean.data}" var="elem">
<h:column>
<h:panelGroup binding="#{elem.displayComponent}"/>
</h:column>
</h:dataTable>
一种实现可能是:
public class LabelElement implements CustomElementProvider {
private UIPanel container;
@Override
UIPanel getDisplayComponent() {
if (container == null) {
FacesContext facesContext = FacesContext.getCurrentInstance();
container = (UIPanel) facesContext.getApplication().createComponent(UIPanel.COMPONENT_TYPE);
UIComponent inside = facesContext.getApplication().createComponent(HtmlOutputLabel.COMPONENT_TYPE);
// fill label with data
container.getChildren().add(inside);
}
return container;
}
// ... override setter
}
当支持beanbean
提供控件时,这种方法有效,但当非托管数据对象提供控件时则无效。然后我得到一个例外:
javax.el.PropertyNotFoundException: Target Unreachable, identifier 'elem' resolved to null
有没有办法避免这种情况
到目前为止,我发现StackOverflow主要是有人想使用两个或更多预定义组件中的一个(请参阅)。这是行不通的,因为我希望能够通过编写新的数据对象来扩展系统,这些对象提供自己的组件实现,而无需修改dataTable
的xhtml
代码
我的问题的另一个解决方案是使用不同的接口:
public interface CustomElementProvider {
String getCustomComponentName();
}
然后我呈现这个方法给出的自定义组件。但我不知道该怎么做
[更新]更清楚地说明我想要什么。这是有效的代码:
<h:dataTable value="#{preferences.preferenceList}" var="pref">
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputLabel id="key" value="#{pref.key}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Value"/>
</f:facet>
<h:inputText id="value" value="#{pref.value}"
rendered="#{pref.valueTypeAsString eq 'java.lang.String'
or pref.valueTypeAsString eq 'java.lang.Integer'}"/>
<h:selectBooleanCheckbox id="valueBool" value="#{pref.value}"
rendered="#{pref.valueTypeAsString eq 'java.lang.Boolean'}"/>
<h:selectOneMenu id="valueEnum" value="#{pref.value}"
rendered="#{pref.valueTypeAsString eq 'java.lang.Enum'}">
<f:selectItems value="#{pref.enumEntries}"/>
</h:selectOneMenu>
</h:column>
</h:dataTable>
目前唯一不太好的事情是,我需要为名为
preferences
的支持bean设置一个类似preferences.boolProp
的EL名称,该bean有一个属性boolProp,为什么不使用XHTML而不是Java来声明/创建视图呢?在声明/创建所需的JSF组件树时,XHTML更直观,更不容易出错。如果您真的坚持使用Java代码,那么如果您首先创建并展示(工作!)XHTML等价物会更容易,那么我们可以更容易地告诉您如何在Java中实现同样的功能(您的具体问题与a.o.有着相同的基础;其他阅读材料:)@BalusC是对的。如果需要简单地创建组件,请在具有绑定的复合组件中使用c:If c:choose/when。效果很好。您可以得到一个简单的声明,其中包含一个选项,可以基于任何内容创建某些组件类型。@BalusC这就是问题所在。没有可用的XHTML等价物。事实上,我想要的是一种灵活的方式来编辑数据表中的数据。所以如果我有一个字符串,我想有一个输入字段。对于布尔型,我需要一个复选框,对于将来可能出现的任何情况,我需要一个匹配的花式控件。我可以通过xhtml添加所有具有相应的rendered
属性(如中)的组件来实现这一点,但是我需要事先知道所有类型和匹配组件。
<h:dataTable value="#{preferences.preferenceList}" var="pref">
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputLabel id="key" value="#{pref.key}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Value"/>
</f:facet>
<h:inputText id="value" value="#{pref.value}"
rendered="#{pref.valueTypeAsString eq 'java.lang.String'
or pref.valueTypeAsString eq 'java.lang.Integer'}"/>
<h:selectBooleanCheckbox id="valueBool" value="#{pref.value}"
rendered="#{pref.valueTypeAsString eq 'java.lang.Boolean'}"/>
<h:selectOneMenu id="valueEnum" value="#{pref.value}"
rendered="#{pref.valueTypeAsString eq 'java.lang.Enum'}">
<f:selectItems value="#{pref.enumEntries}"/>
</h:selectOneMenu>
</h:column>
</h:dataTable>
public class BooleanPreference extends PreferenceBase<Boolean> {
public BooleanPreference(String key, Boolean defaultValue, String elName, String description) {
super(key, defaultValue, elName, description);
}
@Override
public Boolean fromString(String strValue) {
return Boolean.valueOf(strValue);
}
@Override
public UIComponent getEditComponent() {
HtmlSelectBooleanCheckbox checkbox = new HtmlSelectBooleanCheckbox();
checkbox.setValueExpression("value", createValueExpression(String.format("#{%s.value}", getElName())));
return checkbox;
}
}