Mantenga p:diálogo abierto cuando se produzca un error de validación después del envío

Resuelto JOTN asked hace 12 años • 6 respuestas

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 poder hacer es que mbean.saveMethod de alguna manera evite que el cuadro de diálogo se cierre si hubo algún problema y solo envíe un mensaje a través de un gruñido. Este es un caso en el que un validador no ayudará porque no hay forma de saber si algún valor 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 sea más lenta porque para abrir o abrir el cuadro de diálogo es necesario acceder al servidor.

JOTN avatar Feb 08 '12 21:02 JOTN
Aceptado

Se onsuccessejecuta si la solicitud ajax fue exitosa (es decir, no hay ningún error de red, excepción no detectada, etc.), no si el método de acción se invocó exitosamente.

Dado un <p:dialog widgetVar="yourWidgetVarName">, puede eliminarlo onsuccessy reemplazarlo por PrimeFaces RequestContext#execute()dentro saveMethod():

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

Nota: PF()se introdujo en PrimeFaces 4.0. En versiones anteriores de PrimeFaces, necesita yourWidgetVarName.hide()en su lugar.

Si prefiere no saturar el controlador con scripts específicos de vistas, puede usar oncompleteen su lugar el cual ofrece un argsobjeto que tiene una validationFailedpropiedad booleana:

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

La if (args)verificación es necesaria porque puede estar ausente cuando ocurre un error de ajax y, por lo tanto, causar un nuevo error de JS cuando intenta salir validationFailedde él; en &amp;lugar de &es obligatorio por el motivo explicado en esta respuesta , refactorice si es necesario a una función JS que invoque como oncomplete="hideDialogOnSuccess(args, 'yourWidgetVarName')"se muestra en Mantener <p:dialog> abierto cuando la validación haya fallado .

Sin embargo, si no hay ningún error de validación y el método de acción se activa correctamente, y aún desea mantener el cuadro de diálogo abierto debido, por ejemplo, a una excepción en la llamada al método de servicio, entonces puede activar manualmente validationFaileddesde truedentro el método de acción del bean de respaldo explícitamente. invocando FacesContext#validationFailed(). P.ej

FacesContext.getCurrentInstance().validationFailed();
BalusC avatar Feb 08 '2012 15:02 BalusC

Usar el oncompleteatributo de tu botón de comando y un script realmente simple te ayudará mucho.

Su cuadro de diálogo y 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 guión sería algo como esto:

<script type="text/javascript">
    function handleDialogSubmit(xhr, status, args) {
        if (args.validationFailed) {
            dialog.show();
        } else {
            dialog.hide();
        }
    }
</script>
Alonso Dominguez avatar Feb 08 '2012 16:02 Alonso Dominguez

Acabo de buscar en Google esta solución . Básicamente, la idea es usar actionListener en lugar de la acción del botón, y en el bean de respaldo agrega un parámetro de devolución de llamada que luego verificará el método oncomplete del botón. Código parcial de muestra:

JSF primero:

<p:commandButton actionListener="#{myBean.doAction}"
   oncomplete="if (!args.validationFailed &amp;&amp; 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 :)

soltysh avatar Nov 07 '2013 11:11 soltysh