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

rdc*_*rng 9 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>
Run Code Online (Sandbox Code Playgroud)

会生成这样的东西:

<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>
Run Code Online (Sandbox Code Playgroud)

所以所有元素显然都有明确的客户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,以防它相关.

Bal*_*usC 13

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

无论如何,为了实现具体的功能要求,您基本上需要一个物理现有组件来表示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>
Run Code Online (Sandbox Code Playgroud)

这将在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>
Run Code Online (Sandbox Code Playgroud)

你可以通过eg引用它们update=":table_#{someDesiredIndex}_name".

也可以看看:


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