#jsf #jsf-2 #dialog #primefaces #modal-dialog
#jsf #jsf-2 #диалоговое окно #primefaces #модальный диалог
Вопрос:
Я создал компонент ui: для использования в качестве всплывающего окна, поэтому я могу создавать множество всплывающих окон, используя стандарт этого шаблона. Компонент представляет собой просто всплывающее окно с двумя кнопками (отмена и отправка) и содержимым, которое можно переопределить, как вы можете видеть здесь:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<ui:component>
<p:dialog widgetVar="#{idPopup}" id="#{idPopup}" modal="#{popup.modal}"
draggable="#{popup.modal}"
rendered="#{popup.visivel}" visible="#{popup.visivel}"
closeOnEscape="false" closable="false" header="#{titulo}"
resizable="false" styleClass="autoWidthDialog" showEffect="fade"
hideEffect="fade">
<h:panelGroup style="width:100%">
<p:focus />
<ui:insert name="conteudo">Nenhum conteúdo definido!</ui:insert>
<h:panelGrid id="#{idPopup}PainelMensagens" style="width:100%">
<p:messages />
</h:panelGrid>
<ui:insert name="barraDeBotoes">
<h:panelGroup layout="block" style="width:100%">
<p:commandButton value="CANCELAR" immediate="true" update="@form"
style="float:right" action="#{controladorPopup.fechar}"
onclick="#{idPopup}.hide();" />
<p:commandButton value="OK" style="float:right"
update="@form formAlerta"
action="#{controladorPopup.submit}"
process="@form" />
</h:panelGroup>
</ui:insert>
</h:panelGroup>
</p:dialog>
</ui:component>
</html>
Проблема возникает, когда я пытаюсь отправить форму без заполнения обязательных полей. Правильное поведение — просто снова показать всплывающее окно с сообщениями, но диалоговое окно отображается дважды: одно с сообщениями, а другое без сообщений.
Вы можете увидеть это поведение здесь:
это одно из применений этого шаблона:
<ui:composition template="../templates/popupSubmit.xhtml">
<ui:param name="titulo" value="Buscar pessoa" />
<ui:param name="popup" value="#{modeloPopupBuscaPessoa}" />
<ui:param name="controladorPopup"
value="#{controladorPopupBuscaPessoa}" />
<ui:define name="conteudo">
<h:panelGroup>
<h:panelGrid columns="2">
<h:outputLabel value="Tipo de cadastro:" style="float:none" />
<h:selectOneMenu value="#{controladorSugestaoPessoa.tipoCadastro}"
immediate="true">
<f:selectItems value="#{carregadorTipoCadastro.itens}" />
<f:ajax event="change" immediate="true" />
</h:selectOneMenu>
</h:panelGrid>
<h:outputText value="Buscar por:" />
<h:selectOneRadio value="#{controladorSugestaoPessoa.tipoBusca}"
immediate="true">
<f:selectItems value="#{carregadorTipoBuscaPessoa.itens}" />
<f:ajax event="change" immediate="true" />
</h:selectOneRadio>
<p:autoComplete value="#{modeloPopupBuscaPessoa.itemSelecionado}"
forceSelection="true" maxResults="10" queryDelay="500"
completeMethod="#{controladorSugestaoPessoa.atualizarSugestoes}"
var="pessoa" itemLabel="#{pessoa.label}" itemValue="#{pessoa}"
converter="#{conversorSelectItem}" />
</h:panelGroup>
</ui:define>
</ui:composition>
И это некоторая польза:
<h:form id="cadastroPessoa">
<ui:include
src="resources/components/popups/modulo_cadastro/popupNovoCadastroPessoa.xhtml">
<ui:param name="idPopup" value="popupNovoCadastroPessoa" />
</ui:include>
<ui:include
src="resources/components/popups/modulo_cadastro/popupCadastroPessoa.xhtml">
<ui:param name="idPopup" value="popupEdicaoCadastroPessoa" />
</ui:include>
<ui:include
src="resources/components/popups/modulo_cadastro/popupBuscaPessoa.xhtml">
<ui:param name="idPopup" value="popupBuscaCadastroPessoa" />
</ui:include>
</h:form>
<h:form id="cadastroProduto">
<ui:include
src="resources/components/popups/modulo_cadastro/popupCadastroProduto.xhtml">
<ui:param name="idPopup" value="popupNovoCadastroProduto" />
</ui:include>
</h:form>
Может кто-нибудь сказать мне, почему это происходит??
Комментарии:
1. Можете ли вы также опубликовать код в шаблоне и клиенте шаблонов, который относится к этому фрагменту?
2. Не уверен, что это причина всей проблемы, но проектирование диалогового окна как включаемого файла несколько странно. Файл тегов или составной компонент — более разумный выбор. Кроме того, диалоговое окно также должно иметь свое собственное
<h:form>
и не должно размещаться внутри любого<h:form>
. Вы не хотите отправлять / обрабатывать все другие поля на странице за пределами диалогового окна в той же форме при отправке полей в диалоговом окне.
Ответ №1:
Я опубликовал тот же вопрос на форуме primefaces (как сказал Томми Чан), и кто-то ответил на это:
Вероятно, вы размещаете свой диалог в форме, которую вы обновляете, которая является nono. Никогда не обновляйте диалоговое окно, только содержимое в диалоговом окне
Я пытался сделать это, пока не увидел, что все мои диалоговые окна имеют атрибут «rendered», поступающий с сервера (просто посмотрите Первый xml), У меня много диалоговых окон в этом приложении, и некоторые из них связаны с другими (на сервере), эти последние находятся в одной форме.
Я сделал что-то другое, я только создал этот код javascript:
function removerDialogo(id) {
setTimeout(function() {
removerDialogoAposIntervalo(id);
}, 100);
}
function removerDialogoAposIntervalo(id) {
id = id.replace(':', '\:');
jQuery('div.ui-dialog')
.find('#' id)
.parent().eq(1)
.remove();
}
и вызвал этот атрибут в диалоговом окне «OnShow»:
<p:dialog widgetVar="#{idPopup}" id="#{idPopup}" modal="#{popup.modal}"
draggable="#{popup.modal}" rendered="#{popup.visivel}"
visible="#{popup.visivel}" closeOnEscape="false" closable="false"
header="#{titulo}" resizable="false" styleClass="autoWidthDialog"
showEffect="fade" hideEffect="fade" onShow="removerDialogo(this.id)">
Мне не нравится делать подобные вещи, но я не могу найти лучшего способа решить эту проблему…
Если кто-нибудь даст мне лучшее решение, я буду благодарен
Комментарии:
1. Ha! Это был мой комментарий на форуме primefaces. (Лирионус прав? ;)) причина, по которой я это сказал, заключалась в том, что в ваших обновлениях указано @form … и в вашем диалоговом окне нет тега form вокруг него … так что это означает, что он находится над вашим диалогом… это означает, что ваш диалог находится в форме.
2. Исправлено с помощью этого ответа, в моем случае я обновлял всю форму, а не только компонент. в результате чего диалоговое окно появляется дважды.
Ответ №2:
В моем случае я не могу использовать метод oncompleteI), чтобы скрыть диалоговое окно, потому что оно должно быть закрыто для некоторой бизнес-логики.
В моем случае я использую вкладки primefaces в пользовательском интерфейсе. Каждый раз, когда я перехожу по вкладкам, а затем нажимаю кнопку, на которой появляется диалоговое окно, количество моих диалогов увеличивается пропорционально, поэтому я использовал простой скрипт jquery, чтобы удалить все дублирующие диалоги из пользовательского интерфейса e UI.
function removeDuplicateDialogs(dialogId) {
\ generally all our components have : character we have to
\ replace ':' with '\:'(applying escape character)
dialogId = dialogId.replace(/:/g, '\:');
var dialogs = jQuery("div[id=" dialogId "]");
var numOfDialogs = dialogs.length;
numOfDialogs = numOfDialogs - 1;
for (var i = 0; i < numOfDialogs; i ) {
jQuery(dialogs[i]).remove();
}
}
Комментарии:
1. Для какого события вы вызываете скрипт?
Ответ №3:
Как я уже говорил на форуме primefaces, вы обновляете свои формы с помощью диалогового окна в нем… вам нужно поместить свои диалоги из вашей формы и обновить их отдельно. Если вам нужно использовать форму в вашем диалоговом окне, поместите ее в свой диалог:
<p:dialog><p:form> </p:form> </p:dialog>
Комментарии:
1. Привет, Рафаэль, как я уже говорил, я попробовал этот подход, но приложение очень большое, и этот подход нельзя использовать с этой композицией в общем виде. Это связано с отношением некоторых диалоговых окон. Для этого мне нужно изменить всю логику приложения… Но, конечно, в следующий раз я все сделаю правильно 🙂 Спасибо.
2. @brevleq Ах, я этого не видел, вы пробовали вместо размещения средств визуализации в своем диалоговом окне поместить его в panelgrid. Я знаю, что это дерьмовое решение, но на данный момент я не могу придумать ничего лучшего: p
Ответ №4:
У меня была такая же проблема с диалогом, решение было размещено в обновлении командной кнопки, которая показывает компоненту диалога конкретный идентификатор компонента диалога, а не идентификатор формы, решение выглядит следующим образом:
<p:dialog id="dialogId">
<p:commandButton value="OK" style="float:right"
update="@form dialogId"
action="#{controladorPopup.submit}"
process="@form"/>
</p:dialog>
Ответ №5:
Я бы проверил, чтобы ваш widgetVar=»#{idPopup}» id =»#{idPopup}» был одинаковым перед отправкой и после отправки формы. Возможно, оно изменилось, и primefaces считает, что оно больше не существует, и создает новое.
Комментарии:
1. идентификатор двух диалоговых окон один и тот же: cadastroEmpresa:popupNovoCadastroEmpresa
2. возможно, задайте вопрос на форуме primefaces … пользователи там очень отзывчивы.
3. widgetVar PrimeFaces и идентификатор JSF не должны совпадать. Я прочитал это «золотое» правило в сообщении самого Оптимуса где-то на форумах. Не могу найти его прямо сейчас.
Ответ №6:
Добавьте oncomplete
атрибут к вашей кнопке отправки и позвольте ему скрыть диалоговое окно:
<p:commandButton value="OK" style="float:right"
update="@form formAlerta"
action="#{controladorPopup.submit}"
process="@form"
oncomplete="#{idPopup}.hide();"/>
Комментарии:
1. Я уже пробовал эту опцию, диалоговое окно открывается дважды, но они немедленно закрываются.
Ответ №7:
размещение форм внутри диалогового окна — не лучший способ решить эту проблему, если вы получаете доступ к своему приложению с помощью iExplorer, диалоги не будут работать при таком подходе
Комментарии:
1. Что-то подобное происходит со мной, я использую ajax для отправки содержимого форм, и каждый раз, когда я нажимаю на кнопку, которая показывает мне диалоговое окно, оно отображает столько диалогов, сколько отправлено через ajax, я видел, что если я обновлю всю страницу, она начнется снова (отображение 1 диалога, 2, 3 и т.д.)
Ответ №8:
Это ужасная ошибка без официального ответа…
Я использую диалоговое окно для отображения карты Google. Способ, которым я справляюсь с ошибкой (с помощью jQuery), заключается в подсчете количества элементов «.map» в DOM в primefaces: dialog.На шоу… Затем я выбираю:последний отображаемый экземпляр .map (или, в вашем случае, любой класс содержимого, с которым вы работаете), и .remove() диалоговое окно, которое его содержит:
Разметка (прибл.):
<pri:dialog onShow="popupOpen();" etc...>
<div id="map" class"map"></div>
</pri:dialog>
JavaScript:
function onShowDialog(){
if($(".map").length > 1){
$cull = $(".map:last");
$cull.closest(".ui-dialog").remove();
}
}
Если вы садист, вы могли бы, вполне комфортно, сделать это однострочником… Я рассматриваю это как ошибку Primefaces. Кнопка закрытия должна полностью уничтожить диалоговое окно.