jsf - open - El diálogo Primefaces se renderiza dos veces
primefaces dynamic dialog (8)
Verificaría que su widgetVar = "# {idPopup}" id = "# {idPopup}" sea el mismo antes de enviar y después de enviar el formulario. Tal vez ha cambiado y las caras primarias piensan que ya no existe y crea una nueva.
Creé un componente ui: para usar como una ventana emergente, así que puedo crear muchas ventanas emergentes utilizando el estándar de esta plantilla. El componente es solo una ventana emergente con dos botones (cancelar y enviar) y un contenido que puede ser modificado, como puede ver aquí:
<!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>
El problema ocurre cuando intento enviar el formulario sin completar los campos requeridos. El comportamiento correcto es simplemente mostrar nuevamente la ventana emergente con mensajes, pero el diálogo se representa dos veces, una con los mensajes y otra sin los mensajes. Puedes ver este comportamiento aquí:
este es un uso de esta plantilla:
<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>
Y estos son algunos usos:
<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>
¿Podría alguien decirme por qué sucede esto?
Agregue el atributo oncomplete
a su botón de envío y permita que oculte el diálogo:
<p:commandButton value="OK" style="float:right"
update="@form formAlerta"
action="#{controladorPopup.submit}"
process="@form"
oncomplete="#{idPopup}.hide();"/>
He publicado la misma pregunta en el foro de Primefaces (como dijo Tommy Chan), y alguien respondió esto:
Probablemente esté colocando su diálogo en el formulario que está actualizando, que es un nono. Nunca actualice el diálogo solo las cosas en el diálogo
Intenté hacer esto hasta que vi que todos mis cuadros de diálogo tenían el atributo "renderizado" proveniente del servidor (solo veo el primer xml), tengo muchos diálogos en esta aplicación y algunos de ellos tienen relación con otros (en el servidor) , estos últimos están en la misma forma.
Hice algo diferente, solo creé este código de 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();
}
y lo llamó al atributo de diálogo "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)">
No me gusta hacer cosas como esta, pero no puedo encontrar una mejor manera de resolver esto ... Si alguien me da una mejor solución, estaré agradecido.
Como dije en el foro de las caras principales, estás actualizando tus formularios con el diálogo en él ... necesitas colocar tus diálogos fuera de tu formulario y actualizarlos por separado. Si necesita usar un formulario en su diálogo, colóquelo en su diálogo:
<p:dialog><p:form> </p:form> </p:dialog>
poner los formularios dentro del diálogo no es la mejor manera de resolverlo, si accede a su aplicación con IExplorer, los diálogos no funcionarán con este enfoque
En mi caso, no puedo utilizar el método oncompleteI) para ocultar el cuadro de diálogo porque debe estar cerrado para alguna lógica comercial.
En mi caso, tengo fichas de Primefaces en UI. Cada vez que navego por las pestañas y luego hago clic en el botón en el que aparece el diálogo, mi número de diálogos aumenta proporcionalmente. Por eso, he usado script simple de jquery para eliminar todo el cuadro de diálogo de duplicación de la UI 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();
}
}
Tuve el mismo problema con un cuadro de diálogo, la solución se colocó en la actualización del CommandButton que muestra el componente de diálogo el ID específico del Componente de diálogo no el id del formulario, la solución se ve así:
<p:dialog id="dialogId">
<p:commandButton value="OK" style="float:right"
update="@form dialogId"
action="#{controladorPopup.submit}"
process="@form"/>
</p:dialog>
Este es un error horrible sin respuesta oficial ...
Estoy usando un diálogo para renderizar un mapa de Google. La forma en que manejo el error (usando JQuery) es contando el número de elementos ".map" en el DOM en las caras principales: dialog.onShow ... Luego selecciono la: última instancia .map renderizada (o en su caso, lo que sea clase de contenido con la que está trabajando) y .remove () el diálogo que lo contiene:
Marcado (aproximado):
<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();
}
}
Si eres un sádico podrías, bastante cómodamente, convertirlo en un trazador de líneas ... Veo esto como un error de Primefaces. El botón de cerrar debería destruir el diálogo.