Maybe it's a dumb question, but in Primefaces's <p:dialog>
there's property which called appendTo
which described in manual as:
Appends the dialog to the element defined by the given search expression.
I can't realize what it useful for?
'appendTo="body" will scroll the dropdown menu along with the body/container scroll.
p-dialog: It is the container element. p-dialog-titlebar: It is the container of the header. p-dialog-title: It is the header element. p-dialog-titlebar-icon: It is the icon container inside the header. p-dialog-titlebar-close: It is the close icon element.
baseZIndex(zIndex)The z-index value. The z-index of all overlay UI components located on a page is calculated based on the value passed to this method. Since an overlay UI component is added, its z-index is increased by one relative to a previously added overlay UI component.
From the PrimeFaces User Guide (currently p. 185):
Do not place dialog inside tables, containers likes divs with relative positioning or with nonvisible overflow defined, in cases like these functionality might be broken. This is not a limitation but a result of DOM model. For example dialog inside a layout unit, tabview, accordion are a couple of examples. Same applies to confirmDialog as well.
You can overcome this by using appendTo="@(body)"
and your dialog
will be attached as a child of the <body>
node.
One of the main dialog
option is modal
and you could quickly end up with your dialog behind the overlay if you are not using appendTo
as shown below:
See also http://forum.primefaces.org/viewtopic.php?f=3&t=16504
Notes:
appendToBody="true"
. This was changed for 5.0.dialog
contains some buttons don't forget to surround them by <h:form>
(see Proper Construct for Primefaces Dialog)The PrimeFaces docs are a bit sparse on this point. appendToBody
/ appendTo
(before 5.0) solves (or tries to solve) a problem where a PrimeFaces component does not get the right z-Index, meaning it does not appear before or behind other elements the way it should. However, this feature is problematic because it can cause other problems like p:commandbutton action doesn't work inside p:dialog
tl;dr:
Do not use appendTo
/ appendToBody
. Instead, Dialogs (along with ConfirmDialog and OverlayPanel) should always be at the root of the component hierarchy, as a direct descendant of <h:body>
. This will make them work reliably. In that case using appendTo
/ appendToBody
is unnecessary.
One good way to accomplish this is to have one (or multiple) separate XHTML files for these components ("dialogs.xhtml"), which then gets included in your main XHTML file or template (for example using <ui:include>
). Another solution is to use a <ui:define>
in combination with a <ui:insert>
if you want the dialogs to remain in the XHTML file where they are used.
Read on for details :-)
Some PrimeFaces components (such as dialogs) should be be displayed on top of other elements.
For example:
If you use <p:dialog ...modal="true">
, and make the dialog visible, you get a dialog in the foreground, appearing above the rest of the page, with the rest of the page covered by a transparent layer.
You can see this for example in the PF Showcase for dialogs (button "Modal").
Behind the scenes, i.e. in the page's DOM, two things happen:
<div>
(the "modal overlay") is created at the end of the <body>
. This div gets the CSS styles: z-index: 1000; position: absolute; opacity: .30;
. This makes it transparent and covering the whole page, to get the "modal" effect.z-index: 1001; position:fixed;
. Note the z-index is one larger than the modal overlay, thus the dialog appears above the overlay.However, this does not always work. The reason for this is an aspect of CSS called the stacking context. The details are a bit complex, but basically it says that the z-index of a page element is only compared to other elements inside the same parent element. In particular, an element may appear behind another element even though it has a higher z-index, if the element with the high z-index is contained in an element with a lower z-index.
The short (safe) version is: To be certain that z-index works as expected, all concerned elements should be siblings in the DOM.
Now, in this particular situation, the modal overlay must be right at the top of the DOM hierarchy (i.e. inside <body>
), otherwise it cannot reliably appear above the rest of the page. However, the div of the dialog itself is somewhere deeper in the DOM (corresponding to the position of the <p:dialog>
tag in the source XHTML). Now we have a problem.
In practice, this means that the overlay may appear above the dialog, thus obscuring and blocking it. Similarly, if the dialog is not modal, it may appear behind other elements in the page.
The insidious thing about this problem is that it depends on the structure of the rest of the page (specifically, whether the rest of the page uses CSS that creates a new stacking context). So <p:dialog>
may appear to work initially, then suddenly shows incorrectly after a change elsewhere.
As explained above, the problem occurs because the HTML rendered for the PrimeFaces component is somewhere deep down in the DOM, while it would need to be a direct child of <body>
for the z-index to work correctly.
When appendToBody
/ appendTo
is used, PrimeFaces will include Javascript in the rendered page which simply moves the DOM node of the PrimeFaces component to the end of <body>
(using JQuery's appendTo function). That way the component is in the right place in the DOM, and z-index works.
While the DOM reorganization performed by appendTo
solves the problem with CSS and z-index, it introduces another (potential) problem:
The client-side DOM no longer corresponds to the server-side page state maintained by JSF (called the view).
Now, one of the central features of JSF is that it expects the client-side HTML/DOM structure to correspond to the the server-side view - after all, JSF constructed the HTML from that view. If that rule is violated (usually by manipulating the DOM client-side), you get all kinds of weird problems, such as JSF ignoring form fields or values in a submit, or overwriting part of your modifications on AJAX updates.
In this case, the problems caused by moving the DOM node of the PrimeFaces component include:
<h:form>
, it will not work properly (because it will not be inside the <form>
tag client-side because of the moving).id
), which caused problems with later submits. This was fixed for PrimeFaces 4.0 ( Issue 5636: Dialog appendToBody & dynamic doesn't remove the old dom element ), but re-occurred in 5.0 (issue #367).This shows that this kind of DOM manipulation "behind JSF's back" is rather risky and should be avoided - thus my advice to not use appendTo
/ appendToBody
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With