Посмотрите в выводе HTML фактический идентификатор клиента
Вам нужно просмотреть сгенерированный HTML-вывод, чтобы узнать правильный идентификатор клиента. Откройте страницу в браузере, щелкните правой кнопкой мыши и просмотрите исходный код . Найдите HTML-представление интересующего компонента JSF и возьмите его в id
качестве идентификатора клиента. Вы можете использовать его абсолютным или относительным способом в зависимости от текущего контейнера именования. См. Следующую главу.
Примечание: если он содержит индекс итерации, например :0:
, :1:
и т. Д. (Потому что он находится внутри итерационного компонента), тогда вам необходимо понимать, что обновление определенного раунда итерации не всегда поддерживается. См. Более подробную информацию в нижней части ответа.
Запоминать NamingContainer
компоненты и всегда давать им фиксированный идентификатор
Если компонент, на который вы хотите ссылаться с помощью процесса / выполнения / обновления / рендеринга ajax, находится внутри одного и того же NamingContainer
родителя, просто укажите его собственный идентификатор.
<h:form id="form">
<p:commandLink update="result">
<h:panelGroup id="result" />
</h:form>
Если он не находится внутри одного и того же NamingContainer
, вам необходимо указать его, используя абсолютный идентификатор клиента. Абсолютный идентификатор клиента начинается с NamingContainer
символа-разделителя, который используется по умолчанию :
.
<h:form id="form">
<p:commandLink update="result">
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result">
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result">
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
<h:form id="form">
<p:commandLink update=":otherform:result">
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
NamingContainer
компоненты, например <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(таким образом, все составные компоненты) и т.д. Вы узнаете их легко, посмотрев на сгенерированном выводе HTML, их ID будет предварять сгенерированный идентификатор клиента всех дочерних компонентов. Обратите внимание: если у них нет фиксированного идентификатора, JSF будет использовать автоматически сгенерированный идентификатор в j_idXXX
формате. Вы должны полностью избегать этого, давая им фиксированный идентификатор. В OmniFacesNoAutoGeneratedIdViewHandler
может быть полезен в этом процессе разработки.
Если вы знаете, что найти javadoc по рассматриваемому UIComponent
вопросу, вы также можете просто проверить там, реализует ли он NamingContainer
интерфейс или нет. Например, HtmlForm
( тег UIComponent
позади <h:form>
) показывает, что он реализует NamingContainer
, но HtmlPanelGroup
( тег UIComponent
позади <h:panelGroup>
) не показывает его, поэтому он не реализует NamingContainer
. Вот javadoc всех стандартных компонентов и javadoc PrimeFaces .
Решение твоей проблемы
Итак, в вашем случае:
<p:tabView id="tabs">
<p:tab id="search">
<h:form id="insTable">
<p:dialog id="dlg">
<h:panelGrid id="display">
Сгенерированный вывод HTML <h:panelGrid id="display">
выглядит следующим образом:
<table id="tabs:insTable:display">
Вам нужно взять именно это в id
качестве идентификатора клиента, а затем использовать префикс с помощью :
в update
:
<p:commandLink update=":tabs:insTable:display">
Обращение за пределами include / tagfile / complex
Если эта командная ссылка находится внутри файла 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 :
Выражение поиска состоит либо из идентификатора (который согласован точно против собственности идентификатора UIComponent
или серии таких идентификаторов , связанных по UINamingContainer#getSeparatorChar
значению символов. Алгоритм поиска должен работает следующим образом , хотя альтернативные alogrithms могут быть использованы до тех пор , как конечный результат тот же:
- Определите,
UIComponent
что будет основой для поиска, остановив его, как только будет выполнено одно из следующих условий:
- Если поисковое выражение начинается с символа-разделителя (называемого «абсолютным» поисковым выражением), базой будет корень
UIComponent
дерева компонентов. Начальный символ-разделитель будет удален, а оставшаяся часть поискового выражения будет рассматриваться как «относительное» поисковое выражение, как описано ниже.
- В противном случае, если это
UIComponent
является NamingContainer
он будет служить в качестве основы.
- В противном случае найдите родителей этого компонента. Если
NamingContainer
встречается, то это будет база.
- В противном случае (если нет
NamingContainer
) корень UIComponent
будет базой.
- Выражение поиска (возможно, измененное на предыдущем шаге) теперь является «относительным» выражением поиска, которое будет использоваться для поиска компонента (если есть), имеющего совпадающий идентификатор, в пределах области действия базового компонента. Матч проводится следующим образом:
- Если поисковое выражение является простым идентификатором, это значение сравнивается со свойством id, а затем рекурсивно проходит через фасеты и дочерние элементы базы
UIComponent
(за исключением того, что если потомок NamingContainer
найден, его собственные фасеты и дочерние элементы не ищутся).
- Если поисковое выражение включает более одного идентификатора, разделенного символом-разделителем, первый идентификатор используется для поиска
NamingContainer
по правилам в предыдущем пункте маркера. Затем будет вызван findComponent()
метод this NamingContainer
, передав остаток поискового выражения.
Обратите внимание, что PrimeFaces также придерживается спецификации JSF, но RichFaces использует «некоторые дополнительные исключения» .
«reRender» использует UIComponent.findComponent()
алгоритм (с некоторыми дополнительными исключениями) для поиска компонента в дереве компонентов.
Эти дополнительные исключения нигде подробно не описаны, но известно, что относительные идентификаторы компонентов (то есть те, которые не начинаются с :
) ищутся не только в контексте ближайшего родителя NamingContainer
, но и во всех других NamingContainer
компонентах в том же представлении (что является относительно кстати дорогая работа).
Никогда не использовать prependId="false"
Если все это по-прежнему не работает, проверьте, не используете ли вы <h:form prependId="false">
. Это завершится ошибкой во время обработки отправки и рендеринга ajax. См. Также этот связанный вопрос: UIForm с prependId = "false" breaks <f: ajax render> .
Ссылка на конкретный итерационный раунд повторяющихся компонентов
Это было в течение длительного времени не представляется возможным ссылаться на конкретный элемент итерация в переборе компонентов , таких как <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 Search Expressions позволяет ссылаться на компоненты через выражения поиска в дереве компонентов JSF. JSF имеет несколько встроенных функций:
@this
: текущий компонент
@form
: родитель UIForm
@all
: весь документ
@none
: ничего
PrimeFaces улучшил это с помощью новых ключевых слов и поддержки составных выражений:
@parent
: родительский компонент
@namingcontainer
: родитель UINamingContainer
@widgetVar(name)
: компонент, идентифицированный данным widgetVar
Вы также можете смешивать эти ключевые слова в составных выражениях, таких как @form:@parent
, @this:@parent:@parent
и т. Д.
PrimeFaces Selectors (PFS), как в, @(.someclass)
позволяет ссылаться на компоненты с помощью синтаксиса селектора jQuery CSS. Например, ссылки на компоненты, имеющие все общие классы стилей в выводе HTML. Это особенно полезно, если вам нужно сослаться на "много" компонентов. Это только требует, чтобы целевые компоненты имели весь идентификатор клиента в выводе HTML (фиксированный или автоматически сгенерированный, не имеет значения). См. Также Как работают селекторы PrimeFaces, как в update = "@ (. MyClass)"?
context.getViewRoot().findComponent(":inputform" + UINamingContainer.getSeparatorChar(context) + "inputtext" );
Также включите xhtml-код.prependId="false"
сохранением моего дня.прежде всего: насколько я знаю, размещение диалога внутри tabview - плохая практика ... вам лучше вынуть его ...
а теперь к вашему вопросу:
извините, мне потребовалось некоторое время, чтобы понять, что именно вы хотели реализовать,
только что сделал в моем веб-приложении, и он работает
как я уже сказал, поместите диалог p: за пределами p: tabView,
оставьте диалог p:, как вы изначально предложили:
<p:dialog modal="true" widgetVar="dlg"> <h:panelGrid id="display"> <h:outputText value="Name:" /> <h:outputText value="#{instrumentBean.selectedInstrument.name}" /> </h:panelGrid> </p:dialog>
и ссылка p: command должна выглядеть так (все, что я сделал, это изменил атрибут обновления)
<p:commandLink update="display" oncomplete="dlg.show()"> <f:setPropertyActionListener value="#{lndInstrument}" target="#{instrumentBean.selectedInstrument}" /> <h:outputText value="#{lndInstrument.name}" /> </p:commandLink>
то же самое работает в моем веб-приложении, и если это не сработает для вас, я думаю, что что-то не так в вашем коде java bean ...
источник
Это потому, что вкладка также является контейнером именования ... ваше обновление должно быть.
update="Search:insTable:display"
То, что вы можете сделать, просто поместите свой диалог вне формы и все еще внутри вкладки, тогда это будет:update="Search:display"
источник
Я знаю, что у BalusC уже есть отличный ответ, но вот небольшой трюк, который я использую, чтобы заставить контейнер сообщить мне правильный clientId .
Вот пример кода, поскольку мои слова могут не описать его лучше всего.
<p:tabView id="tabs"> <p:tab id="search" title="Search"> <h:form id="insTable"> <p:dataTable id="table" var="lndInstrument" value="#{instrumentBean.instruments}"> <p:column> <p:commandLink id="select"
Удалите неудачное обновление в этом компоненте
oncomplete="dlg.show()"> <f:setPropertyActionListener value="#{lndInstrument}" target="#{instrumentBean.selectedInstrument}" /> <h:outputText value="#{lndInstrument.name}" /> </p:commandLink> </p:column> </p:dataTable> <p:dialog id="dlg" modal="true" widgetVar="dlg"> <h:panelGrid id="display">
Добавьте компонент в компонент с идентификатором, который вы пытаетесь обновить, используя обновление, которое не удастся
<p:commandButton id="BogusButton" update="BogusUpdate"></p:commandButton> <h:outputText value="Name:" /> <h:outputText value="#{instrumentBean.selectedInstrument.name}" /> </h:panelGrid> </p:dialog> </h:form> </p:tab> </p:tabView>
Перейдите на эту страницу и просмотрите ошибку. Ошибка: javax.servlet.ServletException: не удается найти компонент для выражения «BogusUpdate», на которое ссылается вкладки: insTable: BogusButton
Таким образом, правильный clientId для использования будет жирным шрифтом плюс идентификатор целевого контейнера (в данном случае отображается)
tabs:insTable:display
источник
Попробуйте сменить
update="insTable:display"
наupdate="display"
. Я считаю, что вы не можете префикс идентификатора таким идентификатором формы.источник