Mantener p: diálogo abierto cuando se produce un error de validación después de enviar
Diálogo de ejemplo mínimo:
<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>
Lo que quiero ser capaz de hacer es tener el mbean.saveMethod de alguna manera evita que el diálogo se cierre si hubo algún problema y solo genera un mensaje a través de growl. Este es un caso en el que un validador no ayudará porque no hay forma de saber si someValue es válido hasta que se envíe un guardado a un servidor back-end. Actualmente hago esto usando el atributo visible y lo apunto a un campo booleano en mbean. Eso funciona, pero hace que la interfaz de usuario más lento porque subir o bajar el cuadro de diálogo requiere golpear el servidor.
6 answers
El onsuccess
se ejecuta si la solicitud ajax en sí tuvo éxito (es decir, no hay error de red, excepción no capturada, etc.), no si el método de acción se invocó con éxito.
Dado un <p:dialog widgetVar="testDialog">
Podría eliminar el onsuccess
y reemplazarlo por PrimeFaces RequestContext#execute()
dentro de saveMethod()
:
if (success) {
RequestContext.getCurrentInstance().execute("PF('testDialog').hide()");
}
Nota: PF()
se introdujo en PrimeFaces 4.0. En versiones anteriores de PrimeFaces, necesita testDialog.hide()
en su lugar.
Si prefiere no saturar el controlador con scripts específicos de la vista, puede usar oncomplete
en su lugar, que ofrece un objeto args
que tiene una propiedad booleana validationFailed
:
<p:commandButton ...
oncomplete="if (args && !args.validationFailed) PF('testDialog').hide()" />
La verificación if (args)
es necesaria porque puede estar ausente cuando se ha producido un error ajax y, por lo tanto, causar un nuevo error JS cuando intenta obtener validationFailed
de ella; el &
en lugar de &
es obligatorio por la razón explicada en esta respuesta , refactorizar si es necesario a una función JS que invoque como oncomplete="hideDialogOnSuccess(args, testDialog)"
como se muestra en Mantenga .
Esta última solución (con un poco de reescritura) debería funcionar para jsf simple h:commandButton
en combinación con un f:ajax
Es desafortunado que PrimeFaces no soporte lo que RichFaces ya soporta: reevaluación de tiempo de solicitud de EL en atributos on*
. De lo contrario también sería capaz de hacer precisamente esto:
<p:commandButton ...
oncomplete="if (#{not facesContext.validationFailed}) PF('testDialog').hide()" />
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-24 16:24:35
Acabo de buscar en Google esta solución. Básicamente, la idea es usar ActionListener en lugar de la acción de button, y en backing bean agregas el parámetro callback que luego se registrará en el método oncomplete de button. Código parcial de muestra:
JSF primero:
<p:commandButton actionListener="#{myBean.doAction}"
oncomplete="if (!args.validationFailed && args.saved) schedulesDialog.hide();" />
Frijol de respaldo:
public void doAction(ActionEvent actionEvent) {
// do your stuff here...
if (ok) {
RequestContext.getCurrentInstance().addCallbackParam("saved", true);
} else {
RequestContext.getCurrentInstance().addCallbackParam("saved", false);
}
}
Espero que esto ayude a alguien:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-13 08:01:17
Usar el atributo oncomplete
de su botón de comando y un script realmente simple le ayudará mucho.
El diálogo y el botón de comando serían algo similar a esto:
<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 sería algo como esto:
<script type="text/javascript">
function handleDialogSubmit(xhr, status, args) {
if (args.validationFailed) {
dialog.show();
} else {
dialog.hide();
}
}
</script>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-08 16:08:55
Uso esta solución:
Código JSF:
<p:dialog ... widgetVar="dlgModify" ... >
...
<p:commandButton value="Save" update="@form" actionListener="#{AdminMB.saveTable}" />
<p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/>
Código de frijol de respaldo:
public void saveTable() {
RequestContext rc = RequestContext.getCurrentInstance();
rc.execute("PF('dlgModify').hide()");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-29 11:43:40
Creo que esta es la solución más limpia. Al hacer esto, no necesita cambiar su código de botones. Esta solución anula el prototipo de función 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 esta manera, puede mantener su código como:
<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();"
actionListener="#{videoBean.saveVideo(video)}" />
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-17 20:07:28
La solución más fácil es no tener ningún "widget.hide", ni en onclick, ni en oncomplete. Elimine las funciones de ocultar y simplemente ponga
visible="#{facesContext.validationFailed}"
Para la etiqueta de diálogo
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-11 15:27:46