【问题标题】:Primefaces's dialog 'appendTo' property, what it useful for?Primefaces 的对话框 'appendTo' 属性,它有什么用?
【发布时间】:2015-07-24 06:11:27
【问题描述】:

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

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

我不知道它有什么用?

【问题讨论】:

    标签: jsf-2 primefaces


    【解决方案1】:

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

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

    您可以通过使用appendTo="@(body)" 来克服这个问题,您的dialog 将作为<body> 节点的子节点附加。

    dialog 的主要选项之一是modal,如果您不使用appendTo,您可能很快就会在覆盖层后面看到您的对话框,如下所示:

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

    【讨论】:

    • 实际上你说我可以将我的<p:dialog> 放在其他地方,但如果它位于其他组件中,我应该使用appendTo 以避免出现问题?如果我将它放在单独的表单中(当然不是嵌套的)并且它是<h:body> 的下一个孩子,我真的不需要它。我对吗?谢谢。
    • This is not a limitation but a result of DOM model. - 有趣的是他们的措辞。这是 PF 的一个限制——技术上没有什么可以阻止他们在绝对定位的容器(如布局单元)内正确定位对话框。他们只是没有那样实施。当然,对话框可能会被overflow: hidden 等容器的边界截断,但这是另一回事。
    【解决方案2】:

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

    tl;博士:

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

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

    继续阅读以了解详细信息:-)


    问题

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

    例如:

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

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

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

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

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

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

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

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

    “appendTo”如何提供帮助

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

    当使用appendToBody / appendTo 时,PrimeFaces 将在呈现的页面中包含 Javascript,它只是将 PrimeFaces 组件的 DOM 节点移动到 <body> 的末尾(使用 JQuery 的 @ 987654324@函数)。这样组件就在 DOM 中的正确位置,并且 z-index 有效。

    使用'appendTo'的问题

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

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

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

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

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

    这表明这种“在 JSF 背后”进行的 DOM 操作相当冒险,应该避免 - 因此我建议不要使用 appendTo / appendToBody

    【讨论】:

    • 非常详细的分析。赞美。但是,我倾向于不同意您提出的解决方案(或者如果它只是作为可能的解决方案之一,则增强它)。我会在模板中关闭</body> 之前创建一个<ui:insert name="dialog"/>,并使用一个<ui:define name="dialog>… </ui:define>,在其中定义该页面的对话框。这样你就可以与页面保持对话
    • @Kukeltje:是的,这也是一个不错的解决方案。这就是我写“一个好方法……”的原因。我只是想举一个简单的例子,它甚至适用于不使用模板的项目。如果您使用模板,您希望知道该怎么做:-)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多