Manter p: diálogo aberto quando ocorre um erro de validação após o envio

Diálogo de exemplo mínimo:

O que eu quero ser capaz de fazer é fazer com que o mbean.saveMethod de alguma forma impeça o fechamento do diálogo se houver algum problema e só enviar uma mensagem através do growl. Este é um caso em que um validador não ajudará porque não há como saber se algumValue é válido até que um salvamento seja enviado para um servidor de backend. Atualmente faço isso usando o atributo visible e aponto para um campo booleano no mbean. Isso funciona, mas torna a interface do usuário mais lenta, porque o pop-up para cima ou para baixo da checkbox de diálogo exige que o servidor seja atingido.

   

    O onsuccess é executado se a solicitação ajax tiver sido bem-sucedida (isto é, se não houver erro de rede, exceção não detectada, etc.), não se o método de ação tiver sido chamado com êxito.

    Dado um Você poderia remover o onsuccess e substituí-lo por PrimeFaces RequestContext#execute() dentro de saveMethod() :

     if (success) { RequestContext.getCurrentInstance().execute("PF('testDialog').hide()"); } 

    Nota: PF() foi introduzido no PrimeFaces 4.0. Em versões mais antigas do PrimeFaces, você precisa de testDialog.hide() .

    Se preferir não sobrecarregar o controlador com scripts específicos da visualização, você poderá usar oncomplete vez de oferecer um object args que tenha uma propriedade boolean validationFailed :

      

    A verificação if (args) é necessária porque pode estar ausente quando um erro ajax ocorreu e, portanto, causar um novo erro JS ao tentar obter validationFailed partir dele; o & em vez de & é obrigatório pelo motivo explicado nesta resposta , refatorar se necessário para uma function JS que você chama como oncomplete="hideDialogOnSuccess(args, testDialog)" como mostrado em Manter aberto quando a validação falhou .

    Esta última solução (com uma pequena reescrita) deve funcionar para jsf h:commandButton simples h:commandButton em combinação com um f:ajax


    É lamentável que o PrimeFaces não suporte o que o RichFaces já suporta: reavaliação em tempo de requisição de EL em atributos on* . Você também seria capaz de fazer exatamente isso:

      

    Eu acabei de pesquisar esta solução . Basicamente, a idéia é usar o actionListener em vez da ação do botão, e no bean de apoio você adiciona o parâmetro callback que será então o método oncomplete do botão check in. Exemplo de código parcial:

    JSF primeiro:

      

    Feijão de apoio:

     public void doAction(ActionEvent actionEvent) { // do your stuff here... if (ok) { RequestContext.getCurrentInstance().addCallbackParam("saved", true); } else { RequestContext.getCurrentInstance().addCallbackParam("saved", false); } } 

    Espero que isso ajude alguém 🙂

    Usando o atributo oncomplete do seu botão de comando e script muito simples irá ajudá-lo muito.

    Seu diálogo e botão de comando seria algo semelhante a isto:

          

    Um script seria algo assim:

      

    Eu uso esta solução:

    Código JSF:

      ...   

    Código do bean de apoio:

     public void saveTable() { RequestContext rc = RequestContext.getCurrentInstance(); rc.execute("PF('dlgModify').hide()"); } 

    Eu acredito que esta é a solução mais limpa. Fazendo isso, você não precisa alterar o código dos botões . Essa solução substitui o protótipo de function de ocultar.

     $(document).ready(function() { PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide() PrimeFaces.widget.Dialog.prototype.hide = function() { var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) { return; // on validation error, prevent closing } this.originalHide(); }; }); 

    Desta forma, você pode manter seu código como:

      

    A solução mais fácil é não ter nenhum “widget.hide”, nem no onclick, nem no oncomplete. Remova as funções de esconder e apenas coloque

     visible="#{facesContext.validationFailed}" 

    para a tag de diálogo