Primefaces的对话'追加到'财产,它有用吗?

时间:2015-05-13 05:48:50

标签: jsf-2 primefaces

也许这是一个愚蠢的问题,但是在Primefaces的<p:dialog>那个名为appendTo的财产中,在手册中描述为:

  

将对话框追加到给定搜索定义的元素   表达

我无法意识到它有用吗?

2 个答案:

答案 0 :(得分:27)

来自PrimeFaces User Guide(目前第185页):

  

不要在对象内放置对话框,容器喜欢具有相对定位的div或具有不可见的div   溢出已定义,在这些功能可能被破坏的情况下。这不是限制   但是DOM模型的结果。例如布局单元内的对话框,tabview,手风琴是一个   几个例子。同样适用于confirmDialog。

您可以使用appendTo="@(body)"来解决此问题,并且您的dialog将作为<body>节点的子级附加。

其中一个主要的dialog选项是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>围绕它们(参见Proper Construct for Primefaces Dialog

答案 1 :(得分:20)

PrimeFaces文档在这一点上有点稀疏。 appendToBody / appendTo(5.0之前)解决(或尝试解决)PrimeFaces组件未获得正确z-Index的问题,这意味着它不会出现在其他元素之前或之后应该。但是,此功能存在问题,因为它可能会导致其他问题,例如p:commandbutton action doesn't work inside p:dialog

<强> TL; DR:

请勿使用appendTo / appendToBody。相反,Dialogs(以及ConfirmDialog和OverlayPanel)应始终位于组件层次结构的根,作为<h:body>的直接后代。这将使它们可靠地工作。在这种情况下,使用appendTo / appendToBody是不必要的。

实现这一目标的一个好方法是为这些组件(&#34; dialogs.xhtml&#34;)提供一个(或多个)单独的XHTML文件,然后将其包含在主XHTML文件或模板中(例如使用<ui:include>)。另一种解决方案是,如果您希望对话框保留在使用它们的XHTML文件中,请将<ui:define><ui:insert>结合使用。

继续阅读详情: - )

问题

某些PrimeFaces组件(如对话框)应显示在其他元素之上。

例如:

如果使用<p:dialog ...modal="true">,并使对话框可见,则会在前景中显示一个对话框,显示在页面的其余部分上方,页面的其余部分由透明层覆盖。 您可以在PF Showcase for dialogs(按钮&#34;模态&#34;)中看到这一点。

在幕后,即在页面的DOM中,会发生两件事:

  • <div>的末尾创建了一个新的<body>(&#34;模态叠加&#34;)。这个div获得了CSS样式:z-index: 1000; position: absolute; opacity: .30;。这使得它透明并覆盖整个页面,以获得&#34;模态&#34;效果。
  • 对话框本身的(现有但不可见)div可见,并获得样式z-index: 1001; position:fixed;。请注意,z-index比模式叠加大1,因此对话框显示在叠加层上方。

然而,这并不总是有效。其原因是CSS的一个方面,称为stacking context。细节有点复杂,但基本上它表示页面元素的z-index仅与同一父元素内的其他元素进行比较。特别是,元素可能出现在另一个元素后面,即使它具有更高的z-index,如果具有高z-index的元素包含在具有更低z-index 的元素中。

短(安全)版本是:为了确保z-index按预期工作,所有相关元素应该是DOM中的兄弟

现在,在这种特殊情况下,模态覆盖必须位于DOM层次结构的顶部(即<body>内),否则它无法可靠地出现在页面的其余部分之上。但是,对话框本身的div位于DOM的更深处(对应于源XHTML中<p:dialog>标记的位置)。 现在我们遇到了问题。

实际上,这意味着叠加层可能出现在对话框上方,从而遮挡并阻挡它。同样,如果对话框不是模态的,它可能会出现在页面中的其他元素后面。

这个问题的阴险之处在于它取决于页面其余部分的结构(具体来说,页面的其余部分是否使用CSS来创建新的堆叠上下文)。因此,<p:dialog>最初可能会起作用,然后在其他地方发生更改后突然显示错误。

如何&#39;追加到&#39;帮助

如上所述,出现问题是因为为PrimeFaces组件呈现的HTML位于DOM的深处,而它需要是<body>的直接子项才能使z-index正常工作。

当使用appendToBody / appendTo时,PrimeFaces将在呈现的页面中包含Javascript,只需将PrimeFaces组件的DOM节点移动到<body>的末尾(使用JQuery&#39; s appendTo函数)。这样,组件就位于DOM中的正确位置,并且z-index可以正常工作。

使用&quot; appendTo&#39;

的问题

虽然appendTo执行的DOM重组解决了CSS和z-index的问题,但它引入了另一个(潜在的)问题:

客户端DOM不再对应于JSF维护的服务器端页面状态(称为视图)。

现在,JSF的一个核心功能是它希望客户端HTML / DOM结构与服务器端视图相对应 - 毕竟,JSF从该视图构造了HTML。如果违反了该规则(通常通过操纵DOM客户端),则会遇到各种奇怪的问题,例如JSF忽略提交中的表单字段或值,或者覆盖AJAX更新中的部分修改。

在这种情况下,移动PrimeFaces组件的DOM节点引起的问题包括:

  • 如果PrimeFaces组件是<h:form>的一部分,它将无法正常工作(因为移动时它不会位于<form>标签客户端内。)
    PrimeFaces文档中实际上提到了这一点以及解决方法:不是将组件放入表单中,而是将表单放在组件中 - 然后表单将随组件一起移动。
  • 如果使用JSF的AJAX功能更新JSF最初呈现PrimeFaces组件的区域,JSF将从DOM中删除要更新的区域,然后再次呈现该组件,因为它不知道它被移动到其他位置。
    在旧版本的PrimeFaces中,这导致组件在DOM中出现两次(具有相同的id),这导致后来提交的问题。这已针对PrimeFaces 4.0(Issue 5636: Dialog appendToBody & dynamic doesn't remove the old dom element)修复,但在5.0(issue #367)中重新出现。

这表明这种DOM操纵&#34;背后的JSF&#34;风险很大,应该避免 - 因此我建议不要使用appendTo / appendToBody