Подивіться у вихідному коді 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)"?