1. ホーム
  2. jsf

[解決済み】PrimeFacesのprocess/updateとJSFのf:ajax execute/renderの属性を理解する。

2022-04-11 14:24:47

質問

具体的にはどのようなものですか? processupdate PrimeFacesでは p:commandXxx コンポーネントと executerenderf:ajax タグを使用しますか?

バリデーション時に機能するのはどっち?また update 属性は、バックエンドからコンポーネントに値を更新するのではなく、何をするのですか?次のことを行ってください。 process 属性は、値をモデルにバインドしますか?具体的にどのような @this , @parent , @all@form を両方の属性で使うのですか?

以下の例は正常に動作していますが、基本的な概念で少し混乱しています。

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

解決方法は?

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

process 属性はサーバーサイドのものであり UIComponent を実装している EditableValueHolder (入力フィールド)または ActionSource (コマンドフィールド)。その process 属性は、スペースで区切られたクライアント ID のリストを使って、フォームの (部分的な) 送信時に JSF ライフサイクル全体を通して正確に処理されなければならないコンポーネントを JSF に指示します。

JSF は次に、リクエスト値を適用します (コンポーネント自身のクライアント ID に基づいて 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リスナーメソッドで現在の入力コンポーネントに基づいて別の入力コンポーネントやUIセクションを更新したい場合によくあります。つまり、他の入力コンポーネントのバリデーションエラーによって、ajaxリスナーメソッドの実行が妨げられないようにしたいのです。

次に @all . には特別な効果はありません。 process 属性の中で、唯一 update 属性で指定します。A process="@all" と全く同じ振る舞いをします。 process="@form" . いずれにせよ、HTMLは複数のフォームを一度に送信することをサポートしていません。

ちなみに @none というのは、絶対に何も処理する必要がない場合に便利かもしれませんが だけ で特定の部分を更新したい。 update 特に、送信された値やアクションリスナーに内容が依存しないセクションは、そうです。

注目すべきは process 属性には いいえ は、HTTPリクエストのペイロード(リクエストパラメータの量)に影響を及ぼします。つまり、デフォルトの HTML 動作である <h:form> は影響を受けません。フォームのサイズが大きく、HTTPリクエストのペイロードを処理に絶対必要なものだけにしたい場合、つまり、以下の条件を満たすものだけにしたい場合、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> は、デフォルトでこの動作になります。

標準のJSFに相当するPrimeFaces固有の processexecute から <f:ajax execute> . PrimeFacesのものはカンマ区切りの文字列をサポートしていますが(個人的にはスペース区切りにこだわることをお勧めしますが)、これは全く同じ動作をします。 @parent キーワードを使用します。また、以下のことも知っておくと便利でしょう。 <p:commandXxx process> はデフォルトで @form 一方 <p:ajax process><f:ajax execute> はデフォルトで @this . 最後に、以下のことも知っておくと便利です。 process はいわゆる "PrimeFaces Selectors" をサポートしています。 update="@(.myClass)" のようなPrimeFacesセレクタはどのように機能するのですか?


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

update 属性はクライアントサイドのもので、すべての UIComponent s. また update 属性は、スペースで区切られたクライアント ID のリストを使って、JavaScript (ajax リクエスト/レスポンスを処理する担当者) に、フォーム送信の応答として HTML DOM ツリーのどの部分が更新される必要があるかを伝えます。

JSFはそのために適切なajaxレスポンスを用意し、それには のみ を更新するために要求された部分。によってカバーされていない他のすべてのコンポーネントをJSFはスキップします。 update 属性を使用することで、レスポンスのペイロードを小さく保つことができます。また、コンポーネントが rendered 属性は false は、レンダーレスポンスフェーズ中にスキップされます。たとえ true であった場合、JavaScript は HTML DOM ツリー内でそれを更新することができません。 false . 代わりにラップするか、その親を更新する必要があります。また Ajax の更新/レンダーは、レンダー属性を持つコンポーネントでは動作しません。 .

通常 のみ というコンポーネントが 本当に は、フォームの (部分的な) 送信時にクライアント側で "refresh" される必要があります。以下の例では、親フォーム全体を @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 すでに)

しかし、この例では、入力とコマンドのコンポーネントの更新は必要ありません。モデルの値を変更しない限り foobar 内側 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>

(メッセージコンポーネントのIDを保持する必要があることに注意してください、さもなければ @(...) は機能しません! もう一度 update="@(.myClass)" のようなPrimeFacesセレクタはどのように機能するのでしょうか? をご覧ください)

@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> によるredirect-after-POST)または ?faces-redirect=true または ExternalContext#redirect() . エフェクトでは process="@form" update="@all" は、非ajax(非部分)送信とまったく同じ効果を持ちます。私のJSFのキャリアにおいて、唯一賢明な使用例は @all は、ajaxリクエスト中に例外が発生した場合に、エラーページ全体を表示するためのものです。以下も参照してください。 AJAX化されたコンポーネントのJSF 2.0例外の正しい対処方法は?

標準のJSFに相当する、PrimeFaces固有の updaterender から <f:ajax render> . PrimeFacesのものはカンマ区切りの文字列をサポートしていますが(個人的にはスペース区切りにこだわることをお勧めしますが)、これは全く同じ動作をします。 @parent キーワードを使用します。どちらも updaterender はデフォルトで @none (これは、"nothing")です。


こちらもご覧ください。