Garder le dialogue p: ouvert quand une erreur de validation se produit après soumettre

dialogue D'exemple Minimal:

<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 pouvoir faire, c'est avoir le mbean.saveMethod empêche d'une façon ou d'une autre le dialogue de se fermer s'il y avait un problème et produit seulement un message par grognement. C'est un cas où un validateur n'aidera pas parce qu'il n'y a aucun moyen de dire si une valeur est valide jusqu'à ce qu'une sauvegarde soit soumise à un serveur d'arrière-plan. Actuellement je fais ceci en utilisant l'attribut visible et le point à un champ booléen dans mbean. Qui fonctionne mais cela rend l'interface utilisateur plus lente parce que surgir ou descendre la boîte de dialogue nécessite de frapper le serveur.

58
demandé sur BalusC 2012-02-08 18:57:52

6 réponses

le onsuccess s'exécute si la requête ajax elle-même a réussi (c.-à-d. qu'il n'y a pas d'erreur réseau, d'exception uncaught, etc.), pas si la méthode action a été invoquée avec succès.

avec un <p:dialog widgetVar="testDialog"> vous pouvez enlever le onsuccess et le remplacer par des PrimeFaces RequestContext#execute() inside saveMethod() :

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

Note: PF() a été introduit dans PrimeFaces 4.0. Dans les versions plus anciennes de PrimeFaces, vous avez besoin de testDialog.hide() à la place.

si vous préférez ne pas encombrer le contrôleur avec des scripts spécifiques à la vue, vous pouvez utiliser oncomplete à la place qui offre un args objet qui a un booléen validationFailed propriété:

<p:commandButton ...
    oncomplete="if (args &amp;&amp; !args.validationFailed) PF('testDialog').hide()" />

le contrôle if (args) est nécessaire parce qu'il peut être absent lorsqu'une erreur ajax s'est produite et ainsi causer une nouvelle erreur JS lorsque vous essayez d'obtenir validationFailed de lui; le &amp; au lieu de & est obligatoire pour la raison expliquée dans cette réponse , refactor si nécessaire à une fonction JS que vous invoquez comme oncomplete="hideDialogOnSuccess(args, testDialog)" comme indiqué dans garder ouvert lorsque la validation a échoué .

cette dernière solution (avec un peu de réécriture) devrait fonctionner pour JSF simple h:commandButton en combinaison avec un f:ajax


il est regrettable que PrimeFaces ne supporte pas ce qui RichFaces prend déjà en charge: demande-temps de ré-évaluation de EL dans on* attributs. Autrement, vous pourriez aussi faire ceci:

<p:commandButton ...
    oncomplete="if (#{not facesContext.validationFailed}) PF('testDialog').hide()" /> 
141
répondu BalusC 2018-04-24 16:24:35

je viens de googler cette solution . Fondamentalement, l'idée est d'utiliser actionListener au lieu de l'action de button, et dans le dos bean vous ajoutez le paramètre callback qui sera alors vérifier dans la méthode oncomplete de button. Exemple de code partiel:

JSF first:

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

background bean:

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

Espérons que cela aide quelqu'un :)

16
répondu Maciej Szulik 2016-07-13 08:01:17

en utilisant l'attribut oncomplete à partir de votre bouton de commande et script très simple vous aidera beaucoup.

votre bouton de dialogue et de commande serait quelque chose de similaire à 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>

et le script serait quelque chose comme ceci:

<script type="text/javascript">
    function handleDialogSubmit(xhr, status, args) {
        if (args.validationFailed) {
            dialog.show();
        } else {
            dialog.hide();
        }
    }
</script>
15
répondu Alonso Dominguez 2012-02-08 16:08:55

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 la fève de soutien:

public void saveTable() {
    RequestContext rc = RequestContext.getCurrentInstance();
    rc.execute("PF('dlgModify').hide()");
}
7
répondu Antaeus 2014-05-29 11:43:40

je crois que c'est la solution la plus propre. En faisant cela, vous n'ont pas besoin de changer votre code de boutons . Cette solution supplante le prototype de la fonction hide.

$(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)}" />
3
répondu Luís Soares 2013-04-17 20:07:28

la solution la plus simple est de ne pas avoir de" widget.se cacher", ni dans onclick, ni dans oncomplete. Enlever les fonctions de cache et juste mettre

visible="#{facesContext.validationFailed}" 

pour la balise de dialogue

0
répondu makkasi 2016-07-11 15:27:46