2

I have a modal with a form, and what I want is first to close the modal from bean (method "cerrarModal") and after execute the AJAX that makes the insert in database (method "crearUsuario"). I saw this question but it didn't work for me.
this is my button:

<b:commandButton value="Guardar" ajax="true" 
                 update="formTblUsuarios:growlMsg formTblUsuarios:tblUsuarios rowModal" 
                 id="btnGuardarUsuario" look="primary" 
                 onclick="ajax:admUsuariosBean.cerrarModal();admUsuariosBean.crearUsuario()" />


And these are my bean methods:

public void cerrarModal() {
    RequestContext.getCurrentInstance().execute("$('#usuarioModal').modal('hide');");
}

public void crearUsuario() {
    try {
        if (this.fachada.crearUsuario(getUsr())) {
            this.reestablecerClave();FacesMessages.info("User created.");
        } else {
            FacesMessages.warning("The user was not created.");
        }
    } catch (Exception e) {
        FacesMessages.error("The user was not created.");
}

But server throws this error:

abr 04, 2018 11:02:14 AM com.sun.faces.lifecycle.InvokeApplicationPhase execute ADVERTENCIA: Failed to parse the expression [#{admUsuariosBean.cerrarModal();admUsuariosBean.crearUsuario()}] javax.el.ELException: Failed to parse the expression [#{admUsuariosBean.cerrarModal();admUsuariosBean.crearUsuario()}] at org.apache.el.lang.ExpressionBuilder.createNodeInternal(ExpressionBuilder.java:145) at org.apache.el.lang.ExpressionBuilder.build(ExpressionBuilder.java:171) at org.apache.el.lang.ExpressionBuilder.createValueExpression(ExpressionBuilder.java:216) at org.apache.el.ExpressionFactoryImpl.createValueExpression(ExpressionFactoryImpl.java:66) at net.bootsfaces.component.ajax.AJAXBroadcastComponent.evalAsValueExpression(AJAXBroadcastComponent.java:74) at net.bootsfaces.component.ajax.AJAXBroadcastComponent.executeAjaxCalls(AJAXBroadcastComponent.java:123) at net.bootsfaces.component.ajax.AJAXBroadcastComponent.broadcast(AJAXBroadcastComponent.java:52) at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790) at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282) at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at com.abcpagos.otis.beans.Filtro.doFilter(Filtro.java:44) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: org.apache.el.parser.ParseException: Encountered " "; "" at line 1, column 32. Was expecting one of: "}" ... "." ... "[" ... ">" ... "gt" ... "=" ... "ge" ... "


I'm using BootsFaces 1.2.0, with PrimeFaces 6.1, JSF 2.2, (XAMPP) Apache Tomcat 7.0.56.
Thanks.

Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
Julian David
  • 311
  • 1
  • 12

2 Answers2

1

You don't need the bean to close the modal form.

<b:commandButton value="Guardar" ajax="true" 
             update="formTblUsuarios:growlMsg formTblUsuarios:tblUsuarios rowModal" 
             id="btnGuardarUsuario" look="primary" 
             actionListener="#{admUsuariosBean.crearUsuario()}"
             oncomplete="$('#usuarioModal').modal('hide')"
 />
Holger
  • 899
  • 2
  • 7
  • 12
  • 1
    Thanks mate but what I need is to close the modal first and after execute bean method. Oncomplete event is executed when ajax call finished, it means that until bean method finished, the modal will always be open, and I need is the otherwise. – Julian David Apr 05 '18 at 14:30
  • Most people want to close the modal if and only if everything's ok. So in most cases, the answer of Holger is the way to go (possibly guarded by a ``). If you don't care about things like validation constraints, have a look at my answer. – Stephan Rauh Apr 05 '18 at 19:52
  • 1
    You can replace oncomplete by onclick and the modal box will be closed before the ajax call. – Holger Apr 06 '18 at 07:30
  • Also see https://showcase.bootsfaces.net/forms/FetchBeanInfos.jsf#basic_usage. This particular demo does it the other way round: it opens the modal if and only if the validation constraints are fulfilled. But you can use the same idea to prevent the modal from closing as long as there are violated validation rules. That's the use-case of `oncomplete`: it's called after processing the JSF request. – Stephan Rauh Apr 07 '18 at 19:41
1

First of all, the answer of @Holger is (mostly) right: your particular use case doesn't require an AJAX call. However, there are use cases requiring two successive AJAX calls, so I'll ask your original question nonetheless.

I've implemented the parser of BootsFaces in a very simple way. The onclick handler may consist of three parts: a JavaScript part that's executed before the AJAX call, the AJAX call, and a second JavaScript part that's executed after sending the AJAX request to the server. Note that the second JavaScript bit is almost certainly executed before the Java code.

In theory, I could have implemented the AJAX engine with multiple AJAX calls in mind. However, I didn't see the point to do so: It's easier to call a Java method calling two methods instead of triggering two AJAX calls, each calling a Java method and each updating the DOM.

But then... never say never. If you really need two consecutive AJAX calls, you can implement this using <b:remoteCommand>. Such a <b:remoteCommand> is a JavaScript function calling a Java method via AJAX and updating the DOM. So you can call the <b:remoteCommand> in the onComplete handler to trigger the second AJAX request.

There's that. However, you simply want to close the modal, so I recommend to implement it like so:

<b:commandButton value="Guardar"
         update="..." 
         onclick="$('#usuarioModal').modal('hide');ajax:admUsuariosBean.crearUsuario()" />
Stephan Rauh
  • 3,069
  • 2
  • 18
  • 37
  • Thanks, but I want to give some context: I validated the form inside the modal, and if I close the modal in the onclick event, the validation is not showed cause the modal was closed. I realized that if the form validation fails, the ajax call is not executed, and my modal can stay open until the validation is OK. That was the reason I created a bean method that closes the modal, and in theory it will be executed only if the validation was successful. I can't neither use ajax calls in oncomplete event, in order to use the event to close the modal and after with the oncomplete, save the form. – Julian David Apr 06 '18 at 14:48
  • 1
    Have a look at https://showcase.bootsfaces.net/forms/FetchBeanInfos.jsf#basic_usage to see how to solve the task with a single AJAX call. The idea is to add a `` tag and an `oncomplete="if(!validationFailed) $('#usuarioModal').modal('hide')"`. That said, it's just an optimization of your solution. The bottom line is your approach works! – Stephan Rauh Apr 07 '18 at 19:45
  • 1
    Thanks, I'm still knowing the framework. It seems that FetchBeanInfos is very useful with Ajax, and I'm trying to implement a better solution using it. – Julian David Apr 09 '18 at 13:17