Подивіться у вихідному коді 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, їх 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"><!-- 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 / composite
Якщо це посилання команд знаходиться у файлі include / tag, а ціль знаходиться поза ним, і, таким чином, ви не обов'язково знаєте ідентифікатор батьківського контейнера іменування поточного контейнера імен, то ви можете динамічно посилатися на нього через 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
виникне a , це буде базою.
- Інакше (якщо цього не
NamingContainer
зустрічається), коренем UIComponent
буде база.
- Пошуковий вираз (можливо, модифікований на попередньому кроці) тепер є "відносним" пошуковим виразом, який буде використовуватися для пошуку компонента (за наявності), який має ідентифікатор, що відповідає, в межах базового компонента. Матч проводиться так:
- Якщо пошуковий вираз є простим ідентифікатором, це значення порівнюється з властивістю id, а потім рекурсивно через грані та діти бази
UIComponent
(за винятком випадків, якщо знайдено нащадка NamingContainer
, його власні грані та діти не шукаються).
- Якщо пошуковий вираз включає більше одного ідентифікатора, розділеного символом роздільника, перший ідентифікатор використовується для пошуку a
NamingContainer
за правилами в попередній точці кулі. Тоді findComponent()
метод цього NamingContainer
буде викликаний, передавши залишок пошукового вираження.
Зверніть увагу, що PrimeFaces також дотримується специфікації JSF, але RichFaces використовує "деякі додаткові винятки" .
"reRender" використовує UIComponent.findComponent()
алгоритм (за деякими додатковими винятками) для пошуку компонента в дереві компонентів.
Ці додаткові винятки ніде детально не описані, але відомо, що відносні ідентифікатори компонентів (тобто ті, що не починаються з :
) шукаються не тільки в контексті найближчого батьківського рівня NamingContainer
, але і у всіх інших NamingContainer
компонентах у тому ж представленні (що є відносно дорога робота до речі).
Ніколи не використовуйте prependId="false"
Якщо це все ще не працює, перевірте, чи не використовуєте ви <h:form prependId="false">
. Це не вдасться під час обробки надсилання та рендерингу ajax. Дивіться також це пов'язане питання: UIForm з prependId = "помилковими" перервами <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 дозволяють посилатися на компоненти через пошукові вирази компонентів 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)"?