Zrozumienie procesu/aktualizacji PrimeFaces i atrybutów JSF f: ajax execute/render

Czym dokładnie są process i update w elementach PrimeFaces p:commandXxx oraz execute i render w znaczniku f:ajax?

Który działa w momencie walidacji? Co robi atrybut update zamiast aktualizować wartość do komponentu z zaplecza? Czy process atrybut bind value to model? Co dokładnie zrobić @this, @parent, @all i @form w obu atrybutach?

Poniższy przykład działa dobrze, ale jestem trochę zdezorientowany w podstawowych pojęciach.

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />
Author: BalusC, 2014-08-16

3 answers

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

Atrybut process jest po stronie serwera i może wpływać tylko na UIComponentS01E01 EditableValueHolder (pola wejściowe) lub ActionSource (pola poleceń). Atrybut process informuje JSF, używając oddzielonej spacjami listy identyfikatorów klienta, które komponenty dokładnie muszą być przetwarzane przez cały cykl życia JSF po (częściowym) przesłaniu formularza.

JSF zastosuje następnie wartości żądania (znalezienie parametru żądania HTTP na podstawie komponentu własne ID klienta, a następnie albo ustawienie go jako przesłaną wartość w przypadku EditableValueHolder komponentów lub kolejkowanie nowego ActionEvent W przypadku komponentów ActionSource), wykonaj konwersję, walidację i aktualizację wartości modelu (tylko komponentyEditableValueHolder) i na koniec wywołaj kolejkowane ActionEvent (ActionSource tylko komponenty). JSF pomija przetwarzanie wszystkich innych komponentów, które nie są objęte atrybutem process. Również komponenty, których atrybut rendered ocenia na false podczas fazy apply request values będą należy również pominąć w ramach ochrony przed manipulowanymi wnioskami.

Zauważ, że w przypadku komponentów ActionSource (takich jak <p:commandButton>) bardzo ważne jest również włączenie samego komponentu do atrybutu process, szczególnie jeśli zamierzasz wywołać akcję związaną z komponentem. Tak więc poniższy przykład, który zamierza przetwarzać tylko niektóre komponenty wejściowe, gdy dany komponent polecenia jest wywoływany, nie zadziała:

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

Przetworzy tylko #{bean.foo} i Nie #{bean.action}. Musisz również dołączyć sam komponent polecenia:

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

Lub, jak najwyraźniej się dowiedziałeś, używając @parent, jeśli zdarzy się, że są jedynymi komponentami mającymi wspólny rodzic:

<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>

Lub, jeśli oba są jedynymi składnikami rodzica UIForm komponentu, wtedy możesz również użyć @form:

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

Jest to czasami niepożądane, jeśli formularz zawiera więcej elementów wejściowych, które chcesz pominąć przetwarzanie, częściej niż często w przypadkach, gdy chcesz zaktualizować inne komponenty wejściowe lub niektóre sekcje interfejsu użytkownika oparte na bieżącym komponencie wejściowym w metodzie Ajax listener. Mianowicie nie chcesz, aby błędy walidacji na innych komponentach wejściowych uniemożliwiały wykonanie metody Ajax listener.

Potem jest @all. Nie ma to żadnego specjalnego efektu w atrybucie process, ale tylko w atrybucie update. A process="@all" zachowuje się dokładnie tak samo jak process="@form". HTML nie obsługuje składanie wielu formularzy jednocześnie.

Jest również @none, które mogą być przydatne, jeśli absolutnie nie musisz niczego przetwarzać, ale tylko chcesz zaktualizować niektóre konkretne części za pomocą update, szczególnie te sekcje, których zawartość nie zależy od przesłanych wartości lub słuchaczy akcji.

Należy zauważyć, że atrybut process ma nie ma wpływu na obciążenie żądania HTTP (ilość parametrów żądania). Znaczenie, the domyślne zachowanie HTML wysyłania "wszystkiego" zawartego w reprezentacji HTML <h:form> nie będzie miało wpływu. Jeśli masz duży formularz i chcesz zmniejszyć obciążenie żądania HTTP tylko do tych absolutnie niezbędnych w przetwarzaniu, tj. tylko tych objętych atrybutem process, możesz ustawić atrybut partialSubmit w komponentach Primefaces Ajax, jak w <p:commandXxx ... partialSubmit="true"> lub <p:ajax ... partialSubmit="true">. Alternatywnie można również użyć <o:form> OmniFaces 3.0+, który domyślnie zachowanie.

Standardowy odpowiednik JSF dla primefaces specific process to execute Z <f:ajax execute>. Zachowuje się dokładnie tak samo, z wyjątkiem tego, że nie obsługuje oddzielonego przecinkami ciągu znaków, podczas gdy PrimeFaces robi (chociaż osobiście polecam trzymać się konwencji rozdzielonej spacjami), ani słowa kluczowego @parent. Ponadto, może być przydatne wiedzieć, że <p:commandXxx process> domyślnie @form while <p:ajax process> i <f:ajax execute> domyślnie @this. Na koniec warto też wiedzieć, że process obsługuje tzw. "Selektory PrimeFaces", Zobacz także jak działają selektory PrimeFaces jak w update="@(.myClass) " praca?


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

Atrybut updatejest po stronie klienta i może mieć wpływ na reprezentację HTML wszystkich UIComponent s. atrybut update informuje JavaScript (ten odpowiedzialny za obsługę żądania/odpowiedzi ajax), używając oddzielonej spacjami listy identyfikatorów klientów, które części w drzewie HTML DOM muszą być zaktualizowane jako odpowiedź na Formularz submit.

JSF przygotuje do tego poprawną odpowiedź ajax, zawierającą tylko żądane Części do aktualizacji. JSF pomija wszystkie inne komponenty, które nie są objęte atrybutem update W odpowiedzi ajax, zachowując tym samym małą ładowność odpowiedzi. Pomijane będą również komponenty, których atrybut rendered ocenia na false podczas fazy odpowiedzi renderowania. Zauważ, że nawet jeśli zwróci true, JavaScript nie może go zaktualizować w drzewie HTML DOM, jeśli początkowo false. Zamiast tego musisz go owinąć lub zaktualizować jego rodzica. Zobacz także Ajax update / render nie działa na komponencie, który renderował atrybut.

Zazwyczaj chcesz zaktualizować tylko komponenty, które naprawdę muszą być "odświeżone" po stronie klienta po (częściowym) przesłaniu formularza. Poniższy przykład aktualizuje cały formularz rodzica za pomocą @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>

(zauważ, że atrybut process jest pominięty, ponieważ domyślnie jest to @form już)

Chociaż może to działać poprawnie, aktualizacja komponentów wejściowych i poleceń jest w tym konkretnym przykładzie niepotrzebna. Jeśli nie zmienisz wartości modelu foo i bar wewnątrz metody action (która z kolei byłaby nieintuicyjna w perspektywie UX), nie ma sensu ich aktualizować. W związku z tym, że nie jest to możliwe, nie jest to możliwe.]}

<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>
[98]}jednakże, to staje się nudne, gdy masz ich wiele. To jeden z powodów, dla których Istnieją selektory PrimeFaces. Te komponenty wiadomości mają w wygenerowanym wyjściu HTML wspólną klasę stylu ui-message, więc należy również wykonać następujące czynności:
<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>

(należy pamiętać, że należy zachować ID w komponentach wiadomości, w przeciwnym razie @(...) nie będzie działać! Ponownie, zobacz jak zrobić selektory PrimeFaces jak w update="@(.myClass) " praca? dla szczegółów)

@parent aktualizuje tylko komponent macierzysty, który obejmuje bieżący komponent i wszystkie rodzeństwo oraz ich dzieci. Jest to bardziej przydatne, jeśli rozdzieliłeś formularz w rozsądne grupy z każdą własną odpowiedzialnością. @this aktualizuje, oczywiście, tylko bieżący komponent. Zwykle jest to konieczne tylko wtedy, gdy trzeba zmienić jeden z własnych atrybutów HTML komponentu w metodzie akcji. Np.

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

Wyobraź sobie, że oncomplete musi współpracować z value, który został zmieniony w action, wtedy ten konstrukt nie zadziałałby, gdyby komponent nie został zaktualizowany, z tego prostego powodu, że oncomplete jest częścią generowanego wyjścia HTML (a więc wszystkie znajdujące się tam wyrażenia EL są oceniane podczas renderowania odpowiedzi).

@all aktualizuje cały dokument, który należy stosować ostrożnie. Zwykle, chcesz użyć prawdziwego żądania GET zamiast zwykłego linku (<a> lub <h:link>) lub przekierowania po postie przez ?faces-redirect=true lub ExternalContext#redirect(). W efektach, process="@form" update="@all" ma dokładnie taki sam efekt jak nie-ajax (nie-częściowy) submit. W całej mojej karierze JSF, jedyny sensowny przypadek użycia I w przypadku wystąpienia wyjątku podczas żądania ajax, napotkane dla @all jest wyświetlanie strony błędu w całości. Zobacz także jaki jest prawidłowy sposób radzenia sobie z wyjątkami JSF 2.0 Dla komponentów AJAXified?

Standardowo JSF jest odpowiednikiem specyficznych dla PrimeFaces update to render z <f:ajax render>. Zachowuje się dokładnie tak samo z tym, że nie obsługuje oddzielonego przecinkami ciągu podczas PrimeFaces jeden robi (chociaż osobiście polecam po prostu trzymać się konwencja oddzielona spacjami), ani słowa kluczowego @parent. Zarówno update jak i render domyślnie @none (czyli "nic").

Zobacz też:

 251
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-25 14:24:20

Jeśli masz problem z zapamiętaniem wartości domyślnych (wiem, że mam...) oto krótki wyciąg z odpowiedzi Balusca:

Component    | Submit          | Refresh
------------ | --------------- | --------------
f:ajax       | execute="@this" | render="@none"
p:ajax       | process="@this" | update="@none"
p:commandXXX | process="@form" | update="@none"
 47
Author: Jaqen H'ghar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-26 21:38:09

Przez proces (w specyfikacji JSF nazywa się execute) mówisz JSF, aby ograniczył przetwarzanie do komponentu, który jest określony, każda inna rzecz jest po prostu ignorowana.

Update wskazuje, który element zostanie zaktualizowany, gdy serwer odpowie na twoje żądanie.

@Wszystkie : każdy komponent jest przetwarzany / renderowany.

@this : komponent żądający z atrybutem execute jest przetwarzany / renderowany.

@formularz : formularz, który zawiera komponent żądający jest przetwarzany/renderowany.

@rodzic : rodzic zawierający komponent żądający jest przetwarzany / renderowany.

Z Primefaces możesz nawet używać selektorów JQuery, zajrzyj na ten blog: http://blog.primefaces.org/?p=1867

 21
Author: faissalb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-16 12:22:47