web-dev-qa-db-ja.com

Primefacesダイアログの「appendTo」プロパティ、それは何のために役立ちますか?

たぶんそれは愚かな質問ですが、Primefacesの<p:dialog>appendToと呼ばれるプロパティがあり、マニュアルでは次のように説明されています。

指定された検索式で定義された要素にダイアログを追加します。

私はそれが何に役立つのか理解できませんか?

21
Anatoly

PrimeFaces User Guide (現在p。185)から:

テーブル内にダイアログを配置しないでください。コンテナは、これらの機能が壊れる可能性がある場合など、相対的な位置付けや非表示のオーバーフローが定義されたdivを好みます。これは制限ではなく、DOMモデルの結果です。たとえば、レイアウトユニット内のダイアログ、タブビュー、アコーディオンはいくつかの例です。同じことがconfirmDialogにも当てはまります。

appendTo="@(body)"を使用することでこれを克服でき、dialog<body>ノードの子として接続されます。

メインのdialogオプションの1つはmodalであり、以下に示すようにappendToを使用していない場合、オーバーレイの背後でダイアログがすぐに表示される可能性があります。

enter image description here

http://forum.primefaces.org/viewtopic.php?f=3&t=16504 も参照してください。


注:

  • PrimeFaces 5.0より前では、設定する属性はappendToBody="true"でした。これは5.0で変更されました。
  • dialogにいくつかのボタンが含まれる場合、<h:form>で囲むことを忘れないでください( Primefacesダイアログの適切な構成 を参照)
28
Mathieu Castets

PrimeFacesのドキュメントは、この点に関して少し疎です。 appendToBody/appendTo(5.0以前)は、PrimeFacesコンポーネントが正しいz-Indexを取得できない、つまり、他の要素の前後に表示されないという問題を解決します(または解決しようとします)どうすべきか。ただし、この機能は p:commandbuttonアクションがp:dialog 内で機能しないなどの他の問題を引き起こす可能性があるため、問題があります。

tl; dr:

appendTo/appendToBodyを使用しないでください。代わりに、ダイアログは(ConfirmDialogおよびOverlayPanelとともに)<h:body>の直接の子孫として、常にコンポーネント階層のルートになければなりません。これにより、確実に機能します。その場合、appendTo/appendToBodyを使用する必要はありません。

これを実現する良い方法の1つは、これらのコンポーネント用に1つ(または複数)の個別のXHTMLファイル(「dialogs.xhtml」)を作成し、メインのXHTMLファイルまたはテンプレートに含めることです(たとえば、<ui:include>を使用)。別の解決策は、ダイアログを使用するXHTMLファイルに残したい場合、<ui:define><ui:insert>と組み合わせて使用​​することです。

詳細をお読みください:-)


問題

一部のPrimeFacesコンポーネント(ダイアログなど)は、他の要素の上に表示する必要があります。

例えば:

<p:dialog ...modal="true">を使用してダイアログを表示すると、ダイアログがフォアグラウンドに表示され、ページの残りの部分の上に表示され、ページの残りの部分は透明なレイヤーで覆われます。これは、たとえば ダイアログのPFショーケース (ボタン「モーダル」)で確認できます。

舞台裏、つまりページのDOMで、2つのことが起こります:

  • 新しい<div>(「モーダルオーバーレイ」)が<body>の最後に作成されます。このdivはCSSスタイルを取得します:z-index: 1000; position: absolute; opacity: .30;。これにより、ページ全体が透明になり、「モーダル」効果が得られます。
  • ダイアログ自体の(既存だが非表示の)divが表示され、スタイリングz-index: 1001; position:fixed;を取得します。 z-indexはモーダルオーバーレイよりも1つ大きいため、ダイアログがオーバーレイの上に表示されることに注意してください。

ただし、これは常に機能するとは限りません。この理由は、CSSの stacking context と呼ばれる側面にあります。詳細は少し複雑ですが、基本的には、ページ要素のz-indexは同じ親要素内の他の要素とのみ比較されるということです。特に、zインデックスが高いzインデックスの高い要素がzインデックスの低い要素に含まれる場合であっても、要素は別の要素の後ろに表示される場合があります。

短い(安全な)バージョンは次のとおりです。z-indexが期待どおりに機能することを確認するには、すべての関連要素はDOMの兄弟である必要があります

現在、この特定の状況では、モーダルオーバーレイはDOM階層の最上部(つまり<body>内)になければなりません。そうでなければ、ページの残りの部分の上に確実に表示できません。ただし、ダイアログ自体のdivはDOMのどこか深いところにあります(ソースXHTMLの<p:dialog>タグの位置に対応)。 問題が発生しました。

実際には、これはオーバーレイがダイアログの上に表示され、そのためダイアログが見えにくくなり、ブロックされることを意味します。同様に、ダイアログがモーダルでない場合、ページ内の他の要素の背後に表示される場合があります。

この問題のsidな点は、ページの残りの構造に依存することです(具体的には、ページの残りの部分が新しいスタックコンテキストを作成するCSSを使用しているかどうか)。したがって、<p:dialog>は最初は動作しているように見えますが、別の場所で変更すると突然誤って表示されます。

「appendTo」がどのように役立つか

上記で説明したように、問題はPrimeFacesコンポーネント用にレンダリングされたHTMLがDOMのどこか深いところにあるために発生しますが、z-indexが正しく機能するには<body>の直接の子である必要があります.

appendToBody/appendToを使用すると、PrimeFacesはレンダリングされたページにJavascriptを組み込みます。これは、単にPrimeFacesコンポーネントのDOMノードを<body>)の最後に移動します (JQueryの appendTo 関数を使用)。これにより、コンポーネントはDOMの適切な場所に配置され、z-indexが機能します。

「appendTo」の使用に関する問題

appendToによって実行されるDOM再編成は、CSSとz-indexの問題を解決しますが、別の(潜在的な)問題をもたらします。

クライアント側のDOMは、JSFが保持するサーバー側のページ状態に対応しなくなりました(viewと呼ばれます)。

現在、JSFの中心的な機能の1つは、クライアント側のHTML/DOM構造がサーバー側のビューに対応することを期待していることです。結局、JSFはそのビューからHTMLを構築しました。そのルールに違反した場合(通常はDOMクライアント側を操作することにより)、JSFがフォームフィールドやサブミットの値を無視したり、AJAXアップデート。

この場合、PrimeFacesコンポーネントのDOMノードを移動することによって引き起こされる問題は次のとおりです。

  • PrimeFacesコンポーネントが<h:form>の一部である場合、(移動のためにクライアント側で<form>タグ内にないため)正しく動作しません。
    これは実際に回避策とともにPrimeFacesのドキュメントで言及されています。コンポーネントをフォームに入れる代わりに、コンポーネントinsideを入れます-フォームはコンポーネントとともに移動します。
  • JSFがPrimeFacesコンポーネントを最初にレンダリングした領域がJSFのAJAX機能を使用して更新された場合、JSFはDOMから更新する領域を削除し、移動されたことがわからないのでコンポーネントを再度レンダリングします他の場所。
    PrimeFacesの古いバージョンでは、これによりコンポーネントがDOMに(同じidで)2回表示され、後の送信で問題が発生しました。これはPrimeFaces 4.0で修正されました( Issue 5636:Dialog appendToBody&dynamicは古いdom要素を削除しません )が、5.0で再発生しました( issue#367 )。

これは、「JSFの背後」でのこの種のDOM操作はかなり危険であり、回避する必要があることを示しています。したがって、appendTo/appendToBodyを使用しないことをお勧めします。

20
sleske