【发布时间】:2012-04-12 09:59:02
【问题描述】:
尝试编写一个允许多个文本输入的复合组件。我读到可以为复合组件定义支持组件,因此我不必编写渲染器或处理程序。我想不通的是如何将复合 xhtml 中声明的操作委托给支持组件。我想我还不太明白这个概念。有人有想法吗?
我正在使用 Tomcat 7、EL 2.2、Spring 3、Mojarra 2.1.7
这是我想使用该组件的方式:
<custom:multiInput value="#{backingBean.inputList}"/>
BackingBean.java 包含一个对象列表:
@Component
@Scope(value="view")
public class BackingBean {
...
private List<Foo> inputList;
....
}
复合组件 multiInput.xhtml 如下所示:
<cc:interface componentType="MultiInput">
<cc:attribute name="value" required="true" type="java.util.List" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:dataTable value="#{cc.attrs.rows}" var="row">
<h:column>
<!-- here will be a selector component in order to select a foo object -->
</h:column>
<h:column>
<h:commandButton value="Remove Row">
<f:ajax execute=":#{cc.clientId}" render=":#{cc.clientId}" listener="#{cc.removeRow(row)}" />
</h:commandButton>
</h:column>
<h:column>
<h:commandButton value="Add Row" rendered="#{cc.lastRow}">
<f:ajax execute=":#{cc.clientId}" render=":#{cc.clientId}" listener="#{cc.addEmptyRow()}" />
</h:commandButton>
</h:column>
</h:dataTable>
</div>
</cc:implementation>
这里是支持组件MultiInput.java:
@FacesComponent(value="MultiInput")
public class MultiInput extends UIInput implements NamingContainer, Serializable{
...
@Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
initRowsFromValueAttribute();
super.encodeBegin(context);
}
public void removeRow(MultiInputRow row) {
// why is this method is never reached when clicking remove button?
}
public void addEmptyRow() {
// why is this method is never reached when clicking add button?
}
public ListDataModel<MultiSelectRow> getRows() {
return (ListDataModel<MultiSelectRow>) getStateHelper().eval(PropertyKeys.rows, null);
}
private void setRows(ListDataModel<MultiSelectRow> rows) {
getStateHelper().put(PropertyKeys.rows, rows);
}
...
}
现在 - removeRow 和 addEmptyRow 永远不会在 MultiInput 上调用。触发了 ajax 请求,但它在某处丢失了。为什么?
【问题讨论】:
-
复合材料或其任何父项上是否有
rendered属性?如果是这样,您是否 100% 在表单提交期间评估true?另请参阅stackoverflow.com/questions/2118656/… 顺便说一句,您在代码中已经有很多红鲱鱼了。简化/重命名时请小心。 -
thx @BalusC,我更新了样本,因此它的“红鲱鱼”更少(希望如此)。是的,我验证了所有父组件
rendered属性都被评估为true。但让我想知道的是stackoverflow.com/questions/2118656/… 中的第 4 点。似乎没有保留支持组件。每次我单击删除或添加按钮CompositeComponentTagHandler.createComponent时,都会创建一个支持组件MultiInput的新实例。但为什么呢? -
我以前创建过类似的组件,它们工作正常。我复制粘贴了您的确切代码(为简单起见,我只用
Object替换了Foo和MultiSelectRow)并且效果很好。您的具体问题是在其他地方引起的,到目前为止发布的代码中没有显示。也许是嵌套形式。也许是一个评估false的rendered属性。谁知道。唯一的区别是我不使用 Spring,因此只在 bean 上使用标准 JSF 注释。
标签: jsf jsf-2 facelets composite-component