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.
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 && !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 &
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
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()" />
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 && 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 :)
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>
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()");
}
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)}" />
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