Посмотрите в выводе HTML фактический идентификатор клиента
Вам необходимо просмотреть сгенерированный вывод HTML, чтобы узнать правильный идентификатор клиента. Откройте страницу в браузере, сделайте правый клик и Просмотр источника . Найдите HTML-представление интересующего компонента JSF и примите его id
в качестве идентификатора клиента. Вы можете использовать его в абсолютном или относительном порядке в зависимости от текущего контейнера именования. См. Следующую главу.
Примечание: если он содержит индекс итерации, такой как :0:
, :1:
и т. Д. (Поскольку он находится внутри итеративного компонента), то вам необходимо понимать, что обновление определенного цикла итерации не всегда поддерживается. Подробнее об этом см. В нижней части ответа.
Запомните NamingContainer
компоненты и всегда присваивайте им фиксированный идентификатор
Если компонент, на который вы хотите сослаться с помощью ajax-процесса / execute / update / render, находится в том же NamingContainer
родительском элементе, просто укажите его собственный идентификатор.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
Если это , а не внутри того же NamingContainer
, то вам нужно сослаться на него, используя абсолютный идентификатор клиента. Абсолютный идентификатор клиента начинается с символа-разделителя NamingContainer
, который по умолчанию :
.
<h:form id="form">
<p:commandLink update="result"> <!-- FAIL! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- OK! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- FAIL! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
<h:form id="form">
<p:commandLink update=":otherform:result"> <!-- OK! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
NamingContainer
компоненты, например, <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(то есть, все составные компоненты) и т. Д. Вы легко узнаете их, посмотрев на сгенерированные Вывод HTML, их идентификатор будет добавлен к сгенерированному идентификатору клиента всех дочерних компонентов. Обратите внимание: если у них нет фиксированного идентификатора, JSF будет использовать автоматически созданный идентификатор в формате j_idXXX
. Вы должны абсолютно избежать этого, дав им фиксированный идентификатор. OmniFaces NoAutoGeneratedIdViewHandler
может помочь в этом во время разработки.
Если вы знаете, что нашли javadoc рассматриваемого UIComponent
, то вы также можете просто проверить, реализует ли он интерфейс NamingContainer
или нет. Например, HtmlForm
(тег UIComponent
позади <h:form>
) показывает, что он реализует NamingContainer
, но HtmlPanelGroup
(UIComponent
позади * 1059) * tag) не показывает его, поэтому он не реализует NamingContainer
. Вот javadoc всех стандартных компонентов и Вот javadoc PrimeFaces .
Решение вашей проблемы
Итак, в вашем случае:
<p:tabView id="tabs"><!-- This is a NamingContainer -->
<p:tab id="search"><!-- This is NOT a NamingContainer -->
<h:form id="insTable"><!-- This is a NamingContainer -->
<p:dialog id="dlg"><!-- This is NOT a NamingContainer -->
<h:panelGrid id="display">
Сгенерированный HTML-вывод <h:panelGrid id="display">
выглядит следующим образом:
<table id="tabs:insTable:display">
Вам нужно взять именно это id
в качестве идентификатора клиента, а затем использовать префикс :
для использования в update
:
<p:commandLink update=":tabs:insTable:display">
Ссылки на внешние ссылки включают / tagfile / смесь
Если эта командная ссылка находится внутри include / tagfile, а цель находится за ее пределами, и, таким образом, вы не обязательно знаете идентификатор родительского контейнера именования текущего контейнера именования, тогда вы можете динамически ссылаться на него через UIComponent#getNamingContainer()
вот так:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
Или, если эта командная ссылка находится внутри составного компонента, а цель находится за ее пределами:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
Или, если командная ссылка и цель находятся внутри одного составного компонента:
<p:commandLink update=":#{cc.clientId}:display">
См. Также Получить идентификатор родительского контейнера именования в шаблоне для атрибута render / update
Как это работает под одеялом
Это все указано как "поисковое выражение" в в UIComponent#findComponent()
javadoc :
A поисковое выражение состоит либо из идентификатора (который точно совпадает со свойством id для UIComponent
, либо из ряда таких идентификаторов, связанных значением символа UINamingContainer#getSeparatorChar
. Алгоритм поиска следует действовать следующим образом, хотя могут использоваться альтернативные алогриты, если конечный результат одинаков:
- Определите
UIComponent
, который будет основой для поиска, остановив его, как только будет выполнено одно из следующих условий:
- Если поисковое выражение начинается с символа-разделителя (называемого «абсолютным» поисковым выражением), основой будет корень
UIComponent
дерева компонентов.Символ начального разделителя будет удален, а оставшаяся часть поискового выражения будет обрабатываться как «относительное» поисковое выражение, как описано ниже. - В противном случае, если это
UIComponent
является NamingContainer
, оно будетслужить основой. - В противном случае найдите родителей этого компонента.Если встречается
NamingContainer
, это будет основание. - В противном случае (если не обнаружено
NamingContainer
) корень UIComponent
будет основанием.
- Поисковое выражение (возможно, измененное на предыдущем шаге) теперь является «относительным» поисковым выражением, которое будет использоваться для определения местоположения компонента (если есть), который имеет идентификатор, который совпадает, в области действия базового компонента.Соответствие выполняется следующим образом:
- Если поисковое выражение является простым идентификатором, это значение сравнивается со свойством id, а затем рекурсивно проходит через фасеты и дочерние элементы базы
UIComponent
(за исключением того, что если aпотомок NamingContainer
найден, его собственные фасеты и дочерние элементы не ищутся). - Если выражение поиска содержит более одного идентификатора, разделенного символом-разделителем, первый идентификатор используется для определения
NamingContainer
поправила в предыдущем пункте.Затем будет вызван метод findComponent()
этого NamingContainer
, передав остаток выражения поиска.
Обратите внимание, что PrimeFaces также придерживается спецификации JSF, но RichFaces использует «некоторые дополнительные исключения» .
"reRender" использует алгоритм UIComponent.findComponent()
(с некоторыми дополнительными исключениями) для поиска компонента в дереве компонентов.
Эти дополнительные исключенияподробно нигде не описываются, но известно, что относительные идентификаторы компонентов (т. е. не начинающиеся с :
) ищутся не только в контексте ближайшего родителя NamingContainer
, но и во всех других компонентах NamingContainer
в том жеview (кстати, это довольно дорогая работа).
Никогда не используйте prependId="false"
Если все это по-прежнему не работает, то убедитесь, что вы не используете <h:form prependId="false">
,Это не удастся во время обработки ajax submit и render.Смотрите также этот связанный вопрос: UIForm с prependId = "false" разрывы.
Ссылка на конкретный цикл итерации итерационных компонентов
Долгое время было невозможно ссылаться на конкретный итеративный элемент в итерационных компонентах, таких как <ui:repeat>
и <h:dataTable>
, например, так:
<h:form id="form">
<ui:repeat id="list" value="#{['one','two','three']}" var="item">
<h:outputText id="item" value="#{item}" /><br/>
</ui:repeat>
<h:commandButton value="Update second item">
<f:ajax render=":form:list:1:item" />
</h:commandButton>
</h:form>
Однако, так как Mojarra 2.2.5 <f:ajax>
начал поддерживать его (он просто прекратил проверять его; таким образом, вы никогда больше не столкнетесь с упомянутым в вопросе исключением; другое исправление улучшения запланировано начто позже).
Это пока не работает только в текущих версиях MyFaces 2.2.7 и PrimeFaces 5.2.Поддержка может прийти в будущих версиях.В то же время, вам лучше всего обновить сам итеративный компонент или родительский элемент в случае, если он не отображает HTML, например <ui:repeat>
.
При использовании PrimeFaces учитывайте выражения поиска или селекторы
Выражения поиска PrimeFaces позволяет ссылаться на компоненты через выражения поиска в дереве компонентов JSF.JSF имеет несколько встроенных функций:
@this
: текущий компонент @form
: родительский UIForm
@all
: весь документ @none
: ничего
В PrimeFaces это улучшено благодаря новым ключевым словам и поддержке составных выражений:
@parent
: родительский компонент @namingcontainer
: родительский UINamingContainer
@widgetVar(name)
: компонент, определяемый данным widgetVar
Вы также можете смешивать эти ключевые слова в составных выражениях, таких как @form:@parent
, @this:@parent:@parent
и т. Д.
Селекторы PrimeFaces (PFS) , как в @(.someclass)
, позволяют ссылаться на компоненты с помощью синтаксиса селектора jQuery CSS.Например, ссылки на компоненты, имеющие общий класс стиля в выводе HTML.Это особенно полезно в случае, если вам нужно сослаться на «много» компонентов.Это только требует, чтобы целевые компоненты имели все идентификаторы клиента в выводе HTML (фиксированные или автоматически сгенерированные, не имеет значения).См. Также Как работают селекторы PrimeFaces, как в update = "@ (. MyClass)"?