72 votes

Keep p: dialog up quand une erreur de validation survient après l'envoi

Exemple Minimal de dialogue:

<p:dialog header="Test Dialog"  
          widgetVar="testDialog"> 
  <h:form> 
    <p:inputText value="#{mbean.someValue}"/> 

    <p:commandButton value="Save" 
                     onsuccess="testDialog.hide()" 
                     actionListener="#{mbean.saveMethod}"/> 
  </h:form>       
</p:dialog> 

Ce que je veux être en mesure de faire est d'avoir du mbean.saveMethod en quelque sorte à prévenir la boîte de dialogue de fermeture s'il y avait un problème et uniquement en sortie un message par le biais de grogner. C'est un cas où un validateur ne va pas aider, car il n'y a aucun moyen de savoir si someValue est valide jusqu'à ce qu'un enregistrement est soumis à un serveur back-end. Actuellement je le fais à l'aide de l'attribut visible et le point à un champ booléen dans mbean. Qui fonctionne, mais il rend l'interface utilisateur plus lent, car sautant vers le haut ou vers le bas de la boîte de dialogue exige de frapper le serveur.

166voto

BalusC Points 498232

Vous pouvez supprimer l' onsuccess et de la remplacer par PrimeFaces' RequestContext#execute():

<p:commandButton value="Save" 
    actionListener="#{mbean.saveMethod}" /> 

avec cela à l'intérieur d' saveMethod():

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

Si vous préférez ne pas encombrer le contrôleur de la vue spécifique des scripts, vous pouvez également envisager d'utiliser oncomplete au lieu qui offre un args objet qui a une valeur de type boolean validationFailed de la propriété:

<p:commandButton value="Save"
    actionListener="#{mbean.saveMethod}"
    oncomplete="if (args &amp;&amp; !args.validationFailed) testDialog.hide()" />

(l' if (args) vérification est nécessaire, car il peut être absent lors de l'ajax erreur s'est produite et ainsi provoquer une nouvelle JS d'erreur lorsque vous essayez d'obtenir de l' validationFailed ; l' &amp; au lieu de & est obligatoire pour la raison expliquée dans cette réponse, refactoriser, si nécessaire, à une fonction JS qui vous invoquez comme oncomplete="hideDialogOnSuccess(args, testDialog)")


Il est malheureux que les PrimeFaces ne prend pas en charge ce RichFaces prend déjà en charge: demande-temps de ré-évaluation de EL en on* attributs. Vous auriez également être en mesure de le faire:

<p:commandButton value="Save"
    actionListener="#{mbean.saveMethod}"
    oncomplete="if (#{not facesContext.validationFailed}) testDialog.hide()" /> 

15voto

Alonso Dominguez Points 3292

L'utilisation de l'attribut oncomplete de votre bouton de commande et d'un script très simple vous aidera beaucoup.

Votre boîte de dialogue et votre bouton de commande ressembleraient à ceci:

 <p:dialog widgetVar="dialog">
   <h:form id="dialogView">
       <p:commandButton id="saveButton" icon="ui-icon-disk"
           value="#{ui['action.save']}"
           update=":dataList :dialogView"
           actionListener="#{mbean.save()}"
           oncomplete="handleDialogSubmit(xhr, status, args)" />
   </h:form>
 </p:dialog>
 

Un script serait quelque chose comme ça:

 <script type="text/javascript">
    function handleDialogSubmit(xhr, status, args) {
        if (args.validationFailed) {
            dialog.show();
        } else {
            dialog.hide();
        }
    }
</script>
 

15voto

soltysh Points 110

Je viens de googler cette solution . En gros, l'idée est d'utiliser actionListener au lieu de l'action du bouton, et en sauvegardant un haricot, vous ajoutez un paramètre de rappel qui sera ensuite archivé dans la méthode oncomplete du bouton. Exemple de code partiel:

JSF en premier:

 <p:commandButton actionListener="#{myBean.doAction}"
   oncomplete="if (!args.validationFailed &amp;&amp; args.saved) schedulesDialog.hide();" />
 

Haricot de soutien:

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

J'espère que ça aide quelqu'un :)

7voto

Antaeus Points 11

J'utilise cette solution:

Code JSF:

 <p:dialog ... widgetVar="dlgModify" ... >
...
<p:commandButton value="Save" update="@form" actionListener="#{AdminMB.saveTable}" />
<p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/>
 

Code de haricot de soutien:

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

3voto

Luís Soares Points 61

Je crois que c'est la solution la plus propre. Pour ce faire, vous n'avez pas besoin de changer le code de vos boutons . Cette solution remplace le prototype de la fonction de masquage.

 $(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();
    };
});
 

De cette façon, vous pouvez garder votre code comme:

 <p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();" 
   actionListener="#{videoBean.saveVideo(video)}" />
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X