请参阅基于迭代索引的JSF动态生成的ID

时间:2013-04-16 17:20:24

标签: jsf-2

在JSF中,<ui:repeat/>和类似组件(如PrimeFaces <p:dataTable/>根据迭代索引为子组件生成动态ID,即:

<p:dataTable id="table" var="item" value="#{itemList}">
    <h:outputText id="name" value="#{item.name}"/>
</p:dataTable>

将生成如下内容:

<table id="table">
    <span id="table:0:name">name0</span>
    <span id="table:1:name">name1</span>
    <span id="table:2:name">name2</span>
    ...
    <span id="table:n:name">nameN</span>
</table>

因此所有元素都明确具有不同的客户端ID。我故意跳过<tr/><td/>

因此,<p:ajax ... update=":table:name"/>引用表中的所有名称并且工作正常,<p:ajax ... update=":table:#{someDesiredIndex}:name"/>失败并显示类似于SEVERE: javax.faces.FacesException: Cannot find component with identifier ":table:0:name" in view.事件的消息,但我可以确认该组件存在于标记。是不是可以这样做?

我正在运行GlassFish 3.1.2和Mojarra 2.1.6,以防它相关。

1 个答案:

答案 0 :(得分:12)

它确实不存在于UIViewRoot#findComponent()可遍历的JSF组件树中。它仅存在于生成的HTML输出中。 JSF组件树中只有一个<h:outputText id="name">,而不是你想象的那么多。在生成HTML输出时,它被重复使用了多次。最好的情况是,您可以通过table:name获取物理组件,但这反过来又不存在于HTML DOM树中,因此在执行ajax更新期间document.getElementById()将失败。

为了实现具体的功能需求,您基本上需要一个物理现有组件来表示JSF组件树中的行。如果使用视图构建时标记(例如JSTL <c:forEach>)而不是视图渲染时间标记,则可以在循环中创建它们。

<table id="table">
    <c:forEach items="#{itemList}" var="item" varStatus="loop">
        <tr><td><h:outputText id="table_#{loop.index}_name" value="#{item.name}" /></td></tr>
    </c:forEach>
</table>

这将在JSF组件树中物理创建多个组件,并将其呈现为:

<table id="table">
    <span id="table_0_name">name0</span>
    <span id="table_1_name">name1</span>
    <span id="table_2_name">name2</span>
    ...
    <span id="table_n_name">nameN</span>
</table>

您可以通过以下方式引用它们: update=":table_#{someDesiredIndex}_name"

另见:


更新:由于Mojarra 2.2.5,<f:ajax>不再验证客户端ID,渲染器能够遍历迭代组件以找到正确的迭代轮次渲染。因此,以这种方式引用<f:ajax>中的迭代索引应该可以正常工作。它只在当前的MyFaces 2.2.7 / PrimeFaces 5.1版本中不起作用,但预计它们将在未来版本中赶上它。