2

嗨有这个奇怪的问题,我正在使用Composite Component我编写的一个,我从以前使用 CC 的支持 bean(componentTypebean)中获取值

我不知道如何比仅显示代码更好地描述这一点。我会尽量简明扼要地删掉多余的部分:这是Composite Component定义:

<cc:interface componentType="dynamicFieldGroupList">
   <cc:attribute name="coupletClass" />
   <cc:attribute name="form" default="@form"/>
   <cc:attribute name="list" type="java.util.List" required="true"/>
   <cc:attribute name="fieldNames" type="java.util.List" required="true" />
</cc:interface>

<cc:implementation>
    <h:dataTable value="#{cc.model}" var="currLine">
        <h:column>
            <h:outputText id="inner_control_component" value="Inner Look at currLine:#{currLine}"/>
        </h:column>
    </h:dataTable>
</cc:implementation>

CC bean 定义:

@FacesComponent(value = "dynamicFieldGroupList")
// To be specified in componentType attribute.
@SuppressWarnings({ "rawtypes", "unchecked" })
// We don't care about the actual model item type anyway.
public class DynamicFieldGroupList extends UIComponentBase implements
        NamingContainer
{

    private transient DataModel model;

    @Override
    public String getFamily()
    {
        return "javax.faces.NamingContainer"; // Important! Required for
                                                // composite components.
    }

    public DataModel getModel()
    {
        if (model == null)
        {
            model = new ListDataModel(getList());
        }

        return model;
    }

    private List<Map<String, String>> getList()
    { // Don't make this method public! Ends otherwise in an infinite loop
        // calling itself everytime.
        return (List) getAttributes().get("list");
    }

}

以及使用代码:

<ui:repeat var="group" value="#{currentContact.detailGroups}">
    <h:panelGroup rendered="#{not empty group.values}">
        <h:outputText id="controlMsg" value=" list:#{group.values}" /><br/><br/>
        <utils:fieldTypeGroupList list="#{group.values}"
            fieldNames="#{group.fields}" coupletClass="utils" />
    </h:panelGroup>
</ui:repeat>

id 的文本controlMsg显示正确的值,#{group.values}而 id 组件内的控制输出inner_control_component显示之前使用的值。

值第一次是正确的...

我猜这是使用 CC bean 的根本错误,否则可能是一个错误MyFaces 2.1(我正在使用)

4

2 回答 2

6

这种行为的解释很简单:视图中只定义了一个组件。所以也只有一个支持组件和一个模型。由于模型在第一次获取时延迟加载,因此在父迭代组件的每次迭代中都会重用相同的模型。

<ui:repeat>不会在视图构建期间运行(就像 JSTL 那样),而是在视图渲染期间运行。因此,视图中的组件在物理上没有被迭代的项目那么多<ui:repeat>。如果您正在使用<c:forEach>(或在视图构建期间运行的任何其他迭代标记),那么复合组件的行为将与您预期的一样。

您想更改数据模型在支持组件中的保存方式。您希望为父迭代组件的每次迭代保留一个单独的数据模型。model其中一种方法是按如下方式替换属性:

private Map<String, DataModel> models = new HashMap<String, DataModel>();

public DataModel getModel() {
    DataModel model = models.get(getClientId());
    if (model == null) {
        model = models.put(getClientId(), new ListDataModel(getList()));
    }
    return model;
}

也可以看看:

于 2011-06-27T06:11:53.063 回答
3

这里描述的问题是 JSF 中一个古老的已知问题,被复合组件的使用所隐藏。它是如此重要和如此困难,因此在这里回答我在博客条目中为此创建了一个详细的答案:JSF component state per row for datatables

为了使这个答案简短,我会告诉你这不是 MyFaces 2.1 中的错误。请使用 2.1.1,因为这是 2.1.0 的快速错误修复版本。在 JSF 2.1 中,h:dataTable 有一个名为 rowStatePreserved 的新属性,这种情况只是“这个小宝贝”变得有用的一种情况。只需将 ui:repeat 替换为 h:dataTable 并添加 rowStatePreserved="true"。那会成功的。如果您需要操作模型(添加或删除行),您可以使用 tomahawk t:dataTable 和 t:dataList,但您现在必须获取快照版本。请注意,这是目前(2011 年 6 月)在任何不同的 JSF 框架中都不可用的新东西。

如果您需要更多信息,请继续关注Twitter 上的 MyFaces Team或咨询有关MyFaces 用户和开发邮件列表的专家。

于 2011-06-26T20:33:58.123 回答