Свойство диалогового окна 'appendTo' для Primefaces, для чего оно нужно?

Может быть, это глупый вопрос, но в Primefaces <p:dialog> есть свойство, которое называется appendTo который описан в руководстве как:

Добавляет диалог к ​​элементу, определенному данным поисковым выражением.

Я не могу понять, для чего это полезно?

2 ответа

Решение

Из Руководства пользователя PrimeFaces (в настоящее время стр. 185):

Не размещайте диалог внутри таблиц, контейнерам нравится div с определенным относительным позиционированием или с невидимым переполнением, в случаях, когда эти функциональные возможности могут быть нарушены. Это не ограничение, а результат модели DOM. Например, диалог внутри модуля макета, tabview, accordion - это пара примеров. То же самое относится и к подтверждению диалога.

Вы можете преодолеть это с помощью 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> (см. Правильное построение диалога Primefaces)

Документы PrimeFaces немного скудны по этому вопросу. appendToBody / appendTo (до 5.0) решает (или пытается решить) проблему, при которой компонент PrimeFaces не получает правильный z-индекс, то есть он не отображается перед или позади других элементов так, как должен. Однако эта функция проблематична, потому что она может вызвать другие проблемы, такие как действие p:commandbutton не работает внутри диалога p:

ТЛ; др:

Не использовать appendTo / appendToBody , Вместо этого диалоги (вместе с ConfirmDialog и OverlayPanel) всегда должны быть в корне иерархии компонентов, как прямой потомок <h:body> , Это заставит их работать надежно. В этом случае с помощью appendTo / appendToBody не нужно

Хороший способ сделать это - иметь один (или несколько) отдельных файлов XHTML для этих компонентов ("dialogs.xhtml"), которые затем включаются в ваш основной файл или шаблон XHTML (например, с помощью <ui:include>). Другое решение заключается в использовании <ui:define> в сочетании с <ui:insert> если вы хотите, чтобы диалоги оставались в файле XHTML, где они используются.

Продолжайте читать для деталей:-)


Эта проблема

Некоторые компоненты PrimeFaces (например, диалоговые окна) должны отображаться поверх других элементов.

Например:

Если вы используете <p:dialog ...modal="true"> и сделав диалог видимым, вы получите диалоговое окно на переднем плане, появившееся над остальной частью страницы, а остальная часть страницы будет покрыта прозрачным слоем. Вы можете увидеть это, например, в PF Showcase для диалогов (кнопка "Модальная").

За кулисами, то есть в DOM страницы, происходят две вещи:

  • новый <div> ("модальное наложение") создается в конце <body>, Этот div получает стили CSS: z-index: 1000; position: absolute; opacity: .30;, Это делает его прозрачным и покрывающим всю страницу, чтобы получить "модальный" эффект.
  • (существующий, но невидимый) div самого диалога становится видимым и получает стиль z-index: 1001; position:fixed;, Обратите внимание, что z-индекс больше, чем модальное наложение, поэтому диалоговое окно появляется над наложением.

Однако это не всегда работает. Причиной этого является аспект CSS, называемый стековым контекстом. Детали немного сложны, но в основном это говорит о том, что z-индекс элемента страницы сравнивается только с другими элементами внутри того же родительского элемента. В частности, элемент может появляться за другим элементом, даже если он имеет более высокий z-индекс, если элемент с высоким z-индексом содержится в элементе с более низким z-индексом.

Краткая (безопасная) версия такова: чтобы быть уверенным в том, что z-index работает должным образом, все соответствующие элементы должны быть родственными элементами в DOM.

Теперь, в этой конкретной ситуации, модальное наложение должно быть прямо на вершине иерархии DOM (то есть внутри <body>), иначе он не может надежно отображаться над остальной частью страницы. Тем не менее, div самого диалога находится где-то глубже в DOM (в соответствии с положением <p:dialog> тег в исходном коде XHTML). Теперь у нас есть проблема.

На практике это означает, что наложение может появиться над диалоговым окном, тем самым скрывая и блокируя его. Точно так же, если диалоговое окно не является модальным, оно может появляться позади других элементов на странице.

Коварная вещь в этой проблеме состоит в том, что она зависит от структуры остальной части страницы (в частности, использует ли остальная часть страницы CSS, который создает новый контекст стекирования). Так <p:dialog> может показаться, что сначала работает, а затем неожиданно отображается неправильно после изменения в другом месте.

Как 'appendTo' помогает

Как объяснено выше, проблема возникает из-за того, что HTML-код, отображаемый для компонента PrimeFaces, находится где-то глубоко в DOM, хотя он должен быть прямым потомком <body> для правильной работы z-индекса.

когда appendToBody / appendTo используется, PrimeFaces будет включать Javascript на визуализированной странице, которая просто перемещает DOM-узел компонента PrimeFaces в конец <body> (используя функцию appendTo JQuery). Таким образом, компонент находится в нужном месте в DOM, и z-index работает.

Проблема с использованием 'appendTo'

В то время как реорганизация DOM выполняется appendTo решает проблему с CSS и z-index, она вводит еще одну (потенциальную) проблему:

DOM на стороне клиента больше не соответствует состоянию страницы на стороне сервера, поддерживаемой JSF (так называемое представление).

Теперь одна из главных особенностей JSF состоит в том, что он ожидает, что структура HTML/DOM на стороне клиента будет соответствовать представлению на стороне сервера - в конце концов, JSF построил HTML из этого представления. Если это правило нарушается (обычно путем манипулирования клиентской стороной DOM), вы получаете все виды странных проблем, таких как JSF, игнорирование полей или значений формы в отправке или перезапись части ваших изменений в обновлениях AJAX.

В этом случае проблемы, вызванные перемещением узла DOM компонента PrimeFaces, включают:

  • Если компонент PrimeFaces является частью <h:form>, он не будет работать должным образом (потому что он не будет внутри <form> пометка на стороне клиента из-за переезда).
    Это на самом деле упоминается в документации PrimeFaces вместе с обходным решением: вместо помещения компонента в форму поместите форму внутри компонента - тогда форма будет перемещаться вместе с компонентом.
  • Если область, в которой JSF первоначально визуализировал компонент PrimeFaces, обновляется с использованием функции AJAX JSF, JSF удалит область для обновления из DOM, а затем снова отобразит компонент, поскольку он не знает, что он был перемещен в другое место.
    В старых версиях PrimeFaces это приводило к тому, что компонент появлялся в DOM дважды (с тем же id), что вызвало проблемы с последующими представлениями. Это было исправлено в PrimeFaces 4.0 ( проблема 5636: диалоговое окно appendToBody & dynamic не удаляет старый элемент dom), но снова возникло в 5.0 ( проблема № 367).

Это показывает, что такого рода манипуляции с DOM "за спиной JSF" довольно рискованны, и их следует избегать - поэтому мой совет не использовать appendTo / appendToBody,

Другие вопросы по тегам