Обратитесь к динамически генерируемым идентификаторам 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"
,
Смотрите также:
- Как узнать идентификатор клиента компонента для обновления / рендеринга ajax? Не удается найти компонент с выражением "foo", на которое ссылается "bar"
- JSTL в JSF2 Facelets... имеет смысл?
Обновление: начиная с Mojarra 2.2.5, <f:ajax>
больше не проверяет идентификатор клиента, и средство визуализации способно проходить итерирующие компоненты, чтобы найти правильный итерационный раунд для рендеринга. Так что ссылка на индекс итерации в <f:ajax>
этот способ должен работать нормально. Это только пока не работает в текущих версиях MyFaces 2.2.7 / PrimeFaces 5.1, но ожидается, что они догонят его в следующей версии.