Розуміння процесу / оновлення PrimeFaces та JSF f: ajax Execute / render атрибутів


194

Що саме є processі updateв p:commandXxxкомпонентах PrimeFaces, executeі renderв f:ajaxтегах?

Що працює на момент перевірки? Що робить updateатрибут замість оновлення значення компонента з зворотного кінця? Чи processпов'язує атрибут значення для моделі? Що ж робити @this, @parent, @allі @formв обох атрибутів?

Приклад нижче працює добре, але я трохи заплутався в основних поняттях.

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />

Відповіді:


307

<p:commandXxx process> <p:ajax process> <f:ajax execute>

processАтрибут на стороні сервера і може вплинути тільки UIComponentS , реалізують EditableValueHolder(поля введення) або ActionSource(командні поля). processАтрибут повідомляє JSF, використовуючи розділений пробілами список ідентифікаторів клієнтів, які компоненти точно повинні бути оброблені в протягом всього життєвого циклу JSF після (часткового) відправки форми.

Потім JSF буде застосовувати значення запиту (знаходячи параметр запиту HTTP на основі власного ідентифікатора клієнта компонента, а потім встановлюючи його як подане значення у випадку EditableValueHolderкомпонентів, або в черзі нового ActionEventу випадку ActionSourceкомпонентів), здійснювати перетворення, перевірку та оновлення модельних значень ( EditableValueHolderлише компоненти) і нарешті викликати чергу ActionEvent( ActionSourceлише компоненти). JSF пропустить обробку всіх інших компонентів, які не охоплені processатрибутом. Також компоненти, renderedатрибут яких оцінюється falseпід час фази значень запиту застосувати, також будуть пропущені як частина захисту від підроблених запитів.

Зауважте, що для ActionSourceкомпонентів (таких як <p:commandButton>) дуже важливо, щоб ви також включали сам компонент в processатрибут, особливо якщо ви маєте намір викликати дії, пов'язані з компонентом. Отже нижченаведений приклад, який має намір обробляти лише певні компоненти входу, коли викликається певний компонент команди, не працює:

<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="foo" action="#{bean.action}" />

Це буде лише процес, #{bean.foo}а не той #{bean.action}. Вам також потрібно буде включити сам компонент команди:

<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="@this foo" action="#{bean.action}" />

Або, як ви, очевидно, з’ясували, використовуючи, @parentякщо вони є єдиними компонентами, які мають спільний батьків:

<p:panel><!-- Type doesn't matter, as long as it's a common parent. -->
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@parent" action="#{bean.action}" />
</p:panel>

Або, якщо вони обидва є єдиними компонентами батьківського UIFormкомпонента, ви також можете використовувати @form:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@form" action="#{bean.action}" />
</h:form>

Іноді це небажано, якщо форма містить більше вхідних компонентів, які ви хочете пропустити при обробці, частіше, ніж у випадках, коли ви хочете оновити інший компонент (и) вводу або деякий розділ інтерфейсу на основі поточного компонента введення в метод слухача ajax. Ви не хочете, щоб помилки перевірки інших вхідних компонентів не дозволяли виконувати метод слухача ajax.

Тоді є @all. Це не робить особливого ефекту в processатрибуті, а лише в updateатрибуті. А process="@all"поводиться точно так само, як process="@form". HTML так чи інакше не підтримує надсилання декількох форм.

Існує, до речі, також, @noneщо може бути корисним у випадку, якщо вам абсолютно нічого не потрібно обробляти, а лише хочете оновити деякі конкретні частини за допомогою update, зокрема тих розділів, вміст яких не залежить від поданих значень або дій слухачів.

Слід зазначити, що processатрибут не впливає на корисний навантаження HTTP запиту (кількість параметрів запиту). Значить, на поведінку HTML за замовчуванням при надсиланні "всього", що міститься в представленні HTML <h:form>заповіту, це не вплине. Якщо у вас є велика форма і ви хочете зменшити навантаження HTTP-запиту лише на ці абсолютно необхідні в обробці, тобто лише ці, які охоплені processатрибутом, тоді ви можете встановити partialSubmitатрибут в компонентах PrimeFaces Ajax як у <p:commandXxx ... partialSubmit="true">або <p:ajax ... partialSubmit="true">. Ви також можете налаштувати це "глобально", відредагувавши web.xmlта додавши

<context-param>
    <param-name>primefaces.SUBMIT</param-name>
    <param-value>partial</param-value>
</context-param>

Крім того, ви також можете використовувати <o:form>OmniFaces 3.0+, який за замовчуванням застосовує таку поведінку.

Стандартний JSF, еквівалентний специфічній PrimeFaces, processпоходить executeвід <f:ajax execute>. Він поводиться точно так само, за винятком того, що він не підтримує розділену комою рядок, в той час як PrimeFaces це робить (хоча я особисто рекомендую просто дотримуватися конвенції, розділеної пробілом), а також @parentключового слова. Також може бути корисно знати, що <p:commandXxx process>за замовчуванням до @form, <p:ajax process>а <f:ajax execute>за замовчуванням - @this. Нарешті, також корисно знати, що processпідтримує так звані "селектори PrimeFaces", див. Також Як працюють PrimeFaces селектори, як у update = "@ (. MyClass)"?


<p:commandXxx update> <p:ajax update> <f:ajax render>

updateАтрибут на стороні клієнта і може вплинути на HTML представлення всіх UIComponentс. updateАтрибут повідомляє JavaScript (один відповідає за обробку Ajax запит / відповідь), використовуючи розділений пробілами список ідентифікаторів клієнтів, які в частині необхідності дерева HTML DOM буде оновлюватися по мірі відповіді на формі представити.

Потім JSF підготує правильну відповідь на аякс для цього, що містить лише запитувані частини для оновлення. JSF буде пропускати всі інші компоненти, які не охоплені updateатрибутом у відповіді на ajax, тим самим залишаючи невеликим корисне навантаження відповіді. Також компоненти, чий renderedатрибут оцінюється falseпід час фази відповіді візуалізації, будуть пропущені. Зауважте, що хоча він і повернеться true, JavaScript не може оновити його у дереві HTML DOM, якщо він був спочатку false. Вам потрібно буде обгорнути його або оновити його батьківський натомість. Дивіться також оновлення / рендер Ajax не працює на компоненті, який надав атрибут .

Зазвичай ви хочете оновити лише ті компоненти, які дійсно потрібно " оновити " на стороні клієнта після (часткової) форми надсилання. Наведений нижче приклад оновлює всю батьківську форму через @form:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@form" />
</h:form>

(зауважте, що processатрибут пропущено як @formуже встановлений за замовчуванням )

Хоча це може спрацювати нормально, оновлення компонентів вводу та команди в цьому конкретному прикладі непотрібне. Якщо ви не зміните значення моделі fooта метод barвнутрішнього actionвикористання (що, в свою чергу, буде неінтуїтивним в перспективі UX), немає сенсу їх оновлювати. Компоненти повідомлення є єдиними, які дійсно потребують оновлення:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="foo_m bar_m" />
</h:form>

Однак це стає нудним, коли у вас їх багато. Це одна з причин існування селекторів PrimeFaces. Ці компоненти повідомлень мають у створеному HTML виведенні загальний клас стилів ui-message, тому слід також зробити наступне:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@(.ui-message)" />
</h:form>

(Зверніть увагу , що ви повинні тримати ідентифікатори на компонентах повідомлень, в іншому випадку @(...)не працюватиме! Знову ж , подивіться Як PrimeFaces селектор , як в оновленні = «@ (. MyClass)» робота? Для деталей)

@parentОновлює тільки батьківський компонент, який , таким чином , охоплює поточний компонент і всі брати і сестри та їхні діти. Це корисніше, якщо ви розділили форму в здорових групах з кожною відповідальністю. Ці @thisоновлення, очевидно, тільки поточний компонент. Зазвичай це потрібно лише тоді, коли вам потрібно змінити один із власних HTML-атрибутів компонента в методі дії. Напр

<p:commandButton action="#{bean.action}" update="@this" 
    oncomplete="doSomething('#{bean.value}')" />

Уявіть, що oncompleteпотреби в роботі з тим, valueщо змінено action, тоді ця конструкція не працювала, якби компонент не оновлювався, з простої причини, яка oncompleteє частиною генерованого HTML-виводу (і, таким чином, всі вирази EL там оцінюються під час надання відповіді).

@allОновлює весь документ, який повинен використовуватися з обережністю. Зазвичай, ви хочете використовувати для цього справжній GET-запит або простою посиланням ( <a>або <h:link>) або перенаправленням після POST від ?faces-redirect=trueабо ExternalContext#redirect(). По process="@form" update="@all"суті , має точно такий же ефект, як і безвідмовна (неповна) подача. У всій моїй кар'єрі JSF єдиний розумний випадок використання, з яким я стикався, - @allце відображення сторінки помилок у повному обсязі, якщо виняток виникає під час запиту на ajax. Дивіться також Який правильний спосіб поводження з винятками JSF 2.0 для компонентів AJAXified?

Стандартний JSF, еквівалентний специфічній PrimeFaces, updateпоходить renderвід <f:ajax render>. Він поводиться точно так само, за винятком того, що він не підтримує розділену комою рядок, в той час як PrimeFaces це робить (хоча я особисто рекомендую просто дотримуватися конвенції, розділеної пробілом), а також @parentключового слова. І те, updateі renderза замовчуванням @none(тобто "нічого").


Дивитися також:


Коли я використовую update = "", керована властивість резервного файлу не встановлюється, і моя програма @PostConstruct не працює. Будь-які думки? EDIT: • Якщо ви покладаєтесь, що кероване властивість # {param} присутнє в наступних запитах POST, вам потрібно включити його як <f: param> в компоненти UICommand.
К.Ніколас

може процес / оновлення панеліGroup буде обробляти / оновлювати вміст цієї панеліGroup ex: <h: panelGroup id = "pgId"> // Тексти введення йде сюди <h: panelGroup> <p: commandLink process = "pgId" оновлення = "pgId" />
bob-cac

Thx @BalusC за це дуже приємне пояснення!
ПрограмуванняIsAwsome

2
@Rapster: оскільки processне встановлено, він використовує значення за замовчуванням @form. Це також пояснено у відповіді вище.
BalusC

2
@Roland: це приховує іншу, більш серйозну проблему з конфігурацією програми.
BalusC

54

Якщо вам важко запам'ятати значення за замовчуванням (я знаю, у мене є ...) ось короткий витяг з відповіді BalusC:

Компонент | Подати | Оновити
------------ | --------------- | --------------
f: ajax | Execute = "@ це" | render = "@ жоден"
p: ajax | процес = "@ це" | update = "@ немає"
p: командаXXX | process = "@ форма" | update = "@ немає"

Просто корекція другорядний: значення за замовчуванням processдля p:commandXXXце @all. Плюс це, здається, стосується кожного компонента, що підтримує AJAX, наприклад p:menuitem.
Стефан Рау

1
Привіт @StephanRauh, дякую за коментар. Де ви читали дефолт @all? Наскільки я можу прочитати з відповіді BalusC, він є @form, однак @all, рівнозначним @form. Хороший момент щодо інших компонентів, я думаю, що мені доведеться шукати у вихідному коді, коли час, щоб побачити, до яких компонентів він застосовується, так як я краще не напишу щось, що може бути неправильним
Jaqen H'ghar

1
@ JaqenH'ghar Томас Андрашко розповів мені про шматочки @all. Він повинен знати, останнім часом він знову реалізував двигун AJAX PrimeFaces. Пізніше я двічі перевірив це, але читаючи вихідний код PrimeFaces і переглядаючи запити XHR. Я сподіваюся, що цього разу я це зрозумів, тому що я реалізував AJAX запити BootsFaces для роботи однаково з запитами AJAX PrimeFaces.
Стефан Рау

Неправильно сказати, що за замовчуванням є @all, коли HTML не підтримує подання декількох форм. Розробники повинні знати ефективне значення за замовчуванням (тому Томас може змінити його відповідно). До речі, ці Пункти за замовчуванням неправильно визначені як нульові в Посібнику користувача 6.2.
Марк Дзабель

27

За процесом (у специфікації JSF це називається Execute) ви кажете JSF обмежувати обробку компонентом, який вказаний, а все інше просто ігнорується.

оновлення вказує, який елемент буде оновлений, коли сервер відповість на ваш запит.

@all : кожен компонент обробляється / надається.

@ це : компонент, що запитує, з атрибутом Execute обробляється / надається.

@form : Форма, яка містить запитуючий компонент, обробляється / надається.

@parent : Батько, який містить запитуючий компонент, обробляється / надається.

З Primefaces ви навіть можете використовувати селектори JQuery, перегляньте цей блог: http://blog.primefaces.org/?p=1867


2

Зверніть увагу, що PrimeFaces підтримує стандартні ключові слова JSF 2.0+:

  • @this Поточний компонент.
  • @all Цілий вигляд.
  • @form Найближча предка форма поточного компонента.
  • @none Немає компонентів.

і стандартні ключові слова JSF 2.3+:

  • @child(n) п’ята дитина.
  • @composite Найближчий складовий компонент предка.
  • @id(id) Використовується для пошуку компонентів шляхом їх ідентифікації, ігноруючи структуру дерева компонентів та називаючи контейнери.
  • @namingcontainer Найближчий предок іменує контейнер поточного компонента.
  • @parent Батько поточного компонента.
  • @previous Попередній брат.
  • @next Наступний брат.
  • @root Екземпляр перегляду UIViewRoot, можна використовувати для початку пошуку з кореня замість поточного компонента.

Але він також постачається з деякими ключовими словами PrimeFaces:

  • @row(n) n-й ряд.
  • @widgetVar(name) Компонент із заданим віджетомVar.

І ви навіть можете використовувати щось під назвою "PrimeFaces Selectors", що дозволяє використовувати jQuery Selector API. Наприклад, обробити всі входи в елементі з класом CSS myClass:

process="@(.myClass :input)"

Побачити:


2
Зауважте, що навіть JSF2.3 + підтримує більшість ключових слів.
tandraschko
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.