Диалог Primefaces рендерит дважды - PullRequest
4 голосов
/ 24 октября 2011

Я создал компонент 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>

Проблема возникает, когда я пытаюсь отправить форму без заполнения обязательных полей. Правильное поведение - просто снова показать всплывающее окно с сообщениями, но диалог отображается дважды, один с сообщениями, а другой без сообщений. Вы можете увидеть это поведение здесь:

twice rendering

это одно из применений этого шаблона:

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

Может кто-нибудь сказать мне, почему это происходит ??

Ответы [ 8 ]

4 голосов
/ 26 октября 2011

Я разместил тот же вопрос на форуме Primefaces (как сказал Томми Чан), и кто-то ответил на это:

Вы, вероятно, размещаете свой диалог в обновляемой форме, которая не является,Никогда не обновляйте диалоговое окно, только содержимое диалогового окна

Я пытался делать это, пока не увидел, что все мои диалоговые окна имеют атрибут "рендеринг", поступающий с сервера (просто посмотрите первый 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)">

Мне не нравится делать такие вещи, но я не могу найти лучший способ решить эту проблему ...Если кто-нибудь даст мне лучшее решение, я буду благодарен

3 голосов
/ 17 января 2013

В моем случае я не могу использовать метод oncompleteI), чтобы скрыть диалоговое окно, потому что оно должно быть закрыто для некоторой бизнес-логики.

В моем случае я использую вкладки простых лиц в пользовательском интерфейсе.Каждый раз, когда я перемещаюсь по вкладкам и затем нажимаю кнопку, на которой появляется диалоговое окно, количество моих диалогов увеличивается пропорционально. Поэтому я использовал простой скрипт jquery, чтобы удалить весь диалог дублирования из пользовательского интерфейса e.

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 голос
/ 14 августа 2013

У меня была такая же проблема с диалогом, решение было в обновлении commandButton, которое показывает компоненту диалога конкретный идентификатор компонента диалога, а не идентификатор формы, решение выглядит так:

    <p:dialog id="dialogId">
        <p:commandButton value="OK" style="float:right"
             update="@form dialogId"
             action="#{controladorPopup.submit}"
             process="@form"/>
    </p:dialog>
1 голос
/ 27 октября 2011

Как я уже говорил на форуме Primefaces, вы обновляете свои формы с помощью диалога в нем ... вам нужно вывести свои диалоги из формы и обновлять их отдельно.Если вам нужно использовать форму в диалоге, поместите ее в диалог:

   <p:dialog><p:form> </p:form> </p:dialog>
0 голосов
/ 17 сентября 2013

Это ужасная ошибка без официального ответа ...

Я использую диалог для рендеринга карты Google. Способ обработки ошибки (с использованием JQuery) заключается в подсчете количества элементов «.map» в DOM на primefaces: dialog.onShow ... Затем я выбираю: последний обработанный экземпляр .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. Кнопка закрытия должна полностью уничтожить диалог.

0 голосов
/ 02 ноября 2011

размещение форм внутри диалога - не лучший способ решить эту проблему, если вы обращаетесь к своему приложению с помощью IExplorer, диалоги не будут работать с этим подходом

0 голосов
/ 25 октября 2011

Добавьте атрибут oncomplete к кнопке отправки и дайте скрыть диалоговое окно:

<p:commandButton value="OK" style="float:right"
                 update="@form formAlerta"
                 action="#{controladorPopup.submit}"
                 process="@form"
                 oncomplete="#{idPopup}.hide();"/>
0 голосов
/ 25 октября 2011

Я бы проверил, что ваш widgetVar = "# {idPopup}" id = "# {idPopup}" одинаков перед тем, как отправлять и после отправки формы.Возможно, он изменился, и Primefaces думает, что его больше нет, и создает новый.

...