我在JSF中有一个动态数据表,它有多个输入元素,可以是各种数据类型。输入始终是文本控件,但可以包含数字或文本数据。为了解决这个问题,每个字段都从辅助bean中检索它的converterId:
<h:dataTable id="indexFieldTable" value="#{indexFieldBean.indexField}" var="item">
<h:column id="column">
<h:inputText id="inputID" value="#{item.value}">
<f:converter id="ifConverter" converterId="#{item.converter}" />
<f:validator id="ifValidator" validatorId="#{item.validator}" />
</h:inputText>
</h:column>
</h:dataTable>
但是,渲染时,我收到此错误:Expression Error: Named Object: ' not found.
如果我将converterId硬编码为已知值,则可以正常工作:
<f:converter id="ifConverter" converterId="stringConverter" />
如何动态配置converterId?
答案 0 :(得分:3)
f:
标记特定于组件,而不是迭代项。在视图构建时(当组件在视图的组件树中填充时),#{item}
不可用。它仅在渲染时间内可用。您确实需要将它们的值附加到父bean,而不是迭代项。
要解决此问题,请首先更改Field
类(由#{item}
表示)以获得完整的Converter
和Validator
属性(您可以在Field
创建它们{1}}的结构)。
public class Field {
private Converter converter;
private Validator validator;
// ...
}
然后更改bean以在DataModel
中包装这些字段的集合,并具有通用的转换/验证方法,这些方法委派给DataModel
中当前迭代的项目DataModel#getRowData()
}:
public class Bean {
private List<Field> fields;
private DataModel<Field> fieldModel;
public Bean() {
fields = loadItSomehow();
fieldModel = new ListDataModel<Field>(fields);
}
public Converter getFieldConverter() {
return fieldModel.getRowData().getConverter();
}
public void validateField(FacesContext context, UIComponent component, Object value) throws ValidatorException {
fieldModel.getRowData().getValidator().validate(context, component, value);
}
// ...
}
最后更改视图中的输入字段,如下所示,将h:dataTable
的值绑定到DataModel
,将转换器/验证器绑定到父bean的值,后者又将调用委托给目前已迭代的项目:
<h:dataTable value="#{bean.fieldModel}" var="field">
<h:column>
<h:inputText value="#{field.value}" converter="#{bean.fieldConverter}" validator="#{bean.validateField}" />
...
需要注意的是,这种复杂性并不是由于JSF的性质,而是由于您具有非常具体的功能要求。通常,h:dataTable
用于表示tabluar数据,而不是用于生成动态表单。