Выполните два вызова AJAX в commandButton onclick bootsfaces jsf

У меня есть модальное окно с формой, и я хочу сначала закрыть модальный объект из bean (метод «cerrarModal»), а затем выполнить AJAX, который выполняет вставку в базу данных (метод «crearUsuario»). Я видел этот вопрос, но это не сработало для меня.
это моя кнопка:

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


И это мои методы bean-компонентов:

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.");
}

Но сервер выдает эту ошибку:

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" ... "


Я использую BootsFaces 1.2.0 с PrimeFaces 6.1, JSF 2.2, (XAMPP) Apache Tomcat 7.0.56.
Спасибо.


person Julian David    schedule 04.04.2018    source источник


Ответы (2)


Прежде всего, ответ @Holger (в основном) правильный: ваш конкретный вариант использования не требует вызова AJAX. Однако есть варианты использования, требующие двух последовательных вызовов AJAX, поэтому я все же задам ваш исходный вопрос.

Я реализовал парсер BootsFaces очень простым способом. Обработчик onclick может состоять из трех частей: части JavaScript, которая выполняется до вызова AJAX, вызова AJAX и второй части JavaScript, которая выполняется после отправки запроса AJAX на сервер. Обратите внимание, что второй бит JavaScript почти наверняка выполняется перед кодом Java.

Теоретически я мог бы реализовать движок AJAX, имея в виду несколько вызовов AJAX. Однако я не видел в этом смысла: проще вызвать метод Java, вызывающий два метода, вместо запуска двух вызовов AJAX, каждый из которых вызывает метод Java и каждый обновляет DOM.

Но тогда ... никогда не говори никогда. Если вам действительно нужны два последовательных вызова AJAX, вы можете реализовать это с помощью <b:remoteCommand>. Такой <b:remoteCommand> является функцией JavaScript, вызывающей метод Java через AJAX и обновляющей DOM. Таким образом, вы можете вызвать <b:remoteCommand> в обработчике onComplete для запуска второго запроса AJAX.

Вот это. Однако вы просто хотите закрыть модальное окно, поэтому я рекомендую реализовать его так:

<b:commandButton value="Guardar"
         update="..." 
         onclick="$('#usuarioModal').modal('hide');ajax:admUsuariosBean.crearUsuario()" />
person Stephan Rauh    schedule 05.04.2018
comment
Спасибо, но я хочу дать некоторый контекст: я проверил форму внутри модального окна, и если я закрою модальное окно в событии onclick, проверка не будет отображаться, потому что модальное окно было закрыто. Я понял, что если проверка формы не удалась, вызов ajax не выполняется, и мой модальный модуль может оставаться открытым до тех пор, пока проверка не завершится успешно. По этой причине я создал метод bean-компонента, закрывающий модальное окно, и теоретически он будет выполняться только в том случае, если проверка прошла успешно. Я не могу также использовать вызовы ajax в событии oncomplete, чтобы использовать событие для закрытия модального окна, а затем с помощью oncomplete сохранить форму. - person Julian David; 06.04.2018
comment
Взгляните на showcase.bootsfaces.net/forms/FetchBeanInfos.jsf#basic_usage чтобы увидеть, как решить задачу с помощью одного вызова AJAX. Идея состоит в том, чтобы добавить тег <b:fetchBeanInfo> и oncomplete="if(!validationFailed) $('#usuarioModal').modal('hide')". Тем не менее, это просто оптимизация вашего решения. Суть в том, что ваш подход работает! - person Stephan Rauh; 07.04.2018
comment
Спасибо, я все еще знаю фреймворк. Кажется, что FetchBeanInfos очень полезен с Ajax, и я пытаюсь реализовать лучшее решение, используя его. - person Julian David; 09.04.2018

Для закрытия модальной формы bean-компонент не нужен.

<b:commandButton value="Guardar" ajax="true" 
             update="formTblUsuarios:growlMsg formTblUsuarios:tblUsuarios rowModal" 
             id="btnGuardarUsuario" look="primary" 
             actionListener="#{admUsuariosBean.crearUsuario()}"
             oncomplete="$('#usuarioModal').modal('hide')"
 />
person Holger    schedule 05.04.2018
comment
Спасибо, приятель, но мне нужно сначала закрыть модальное окно, а затем выполнить метод bean-компонента. Событие Oncomplete выполняется, когда вызов ajax завершен, это означает, что до завершения метода bean-компонента модальное окно всегда будет открыто, и мне нужно, чтобы в противном случае. - person Julian David; 05.04.2018
comment
Большинство людей хотят закрыть модальное окно тогда и только тогда, когда все в порядке. Так что в большинстве случаев ответ Хольгера - это правильный путь (возможно, под охраной <b:fetchBeanInfo>). Если вас не волнуют такие вещи, как ограничения валидации, взгляните на мой ответ. - person Stephan Rauh; 05.04.2018
comment
Вы можете заменить oncomplete на onclick, и модальное окно будет закрыто перед вызовом ajax. - person Holger; 06.04.2018
comment
См. Также showcase.bootsfaces.net/forms/FetchBeanInfos.jsf#basic_usage. Эта конкретная демонстрация делает это наоборот: она открывает модальное окно тогда и только тогда, когда выполняются ограничения валидации. Но вы можете использовать ту же идею, чтобы предотвратить закрытие модального окна, пока нарушаются правила проверки. Это вариант использования oncomplete: он вызывается после обработки запроса JSF. - person Stephan Rauh; 07.04.2018