Обратитесь к динамически генерируемым идентификаторам JSF на основе индекса итерации.

В JSF, <ui:repeat/> и аналогичные компоненты, такие как PrimeFaces <p:dataTable/> генерировать динамические идентификаторы для подкомпонентов на основе индекса итерации, то есть:

<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>

таким образом, все элементы имеют четкий идентификатор клиента. Я намеренно пропустил <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 ответ

Решение

Он действительно не существует в дереве компонентов 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>

Это создаст физически несколько компонентов в дереве компонентов 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> больше не проверяет идентификатор клиента, и средство визуализации способно проходить итерирующие компоненты, чтобы найти правильный итерационный раунд для рендеринга. Так что ссылка на индекс итерации в <f:ajax> этот способ должен работать нормально. Это только пока не работает в текущих версиях MyFaces 2.2.7 / PrimeFaces 5.1, но ожидается, что они догонят его в следующей версии.

Другие вопросы по тегам