Держите P: диалоговое окно открыто, когда ошибка проверки возникает после отправки


минимальный пример диалога:

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

то, что я хочу быть в состоянии сделать это на MBean.saveMethod каким-то образом предотвращает закрытие диалога, если возникла какая-то проблема, и выводит сообщение только через growl. Это случай, когда валидатор не поможет, потому что нет способа определить, действительно ли someValue, пока сохранение не будет отправлено на внутренний сервер. В настоящее время я делаю это с помощью атрибута visible и указываю его на логическое поле в mbean. Это работает, но это делает пользователь интерфейс медленнее, потому что выскакивает вверх или вниз диалог требует удара по серверу.

6 58

6 ответов:

The onsuccess выполняется, если сам запрос ajax был успешным (т. е. нет сетевой ошибки, неперехваченного исключения и т. д.), а не если метод действия был успешно вызван.

дали <p:dialog widgetVar="testDialog"> убрать onsuccess и заменить его на PrimeFaces RequestContext#execute() внутри saveMethod():

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

Примечание: PF() был введен в PrimeFaces 4.0. В старых версиях PrimeFaces вам нужно .

если вы предпочитаете не загромождать контроллер с просмотр конкретных сценариев, вы можете использовать oncomplete вместо этого предлагает args объект, который имеет логическое validationFailed свойства:

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

The if (args) проверка необходима, потому что она может отсутствовать при возникновении ошибки ajax и, таким образом, вызвать новую ошибку JS при попытке получить validationFailed от нее;&amp; вместо & является обязательным по причине, указанной в ответ, рефакторинг при необходимости для функции JS, которую вы вызываете как oncomplete="hideDialogOnSuccess(args, testDialog)" как показано в держите открытым, когда проверка не удалась.

это последнее решение (с небольшим переписыванием) должно работать для простого jsf h:commandButton в сочетании с f:ajax


жаль, что PrimeFaces не поддерживает то, что уже поддерживает RichFaces: request-time re-evaluation of EL in on* атрибуты. В противном случае вы также сможете сделать именно это:

<p:commandButton ...
    oncomplete="if (#{not facesContext.validationFailed}) PF('testDialog').hide()" /> 

Я только что погуглил данное решение. В основном идея состоит в том, чтобы использовать actionListener вместо действия кнопки, а в backing bean вы добавляете параметр обратного вызова, который затем будет проверять метод onComplete кнопки. Пример частичного кода:

JSF первый:

<p:commandButton actionListener="#{myBean.doAction}"
   oncomplete="if (!args.validationFailed &amp;&amp; args.saved) schedulesDialog.hide();" />

базовый компонент:

public void doAction(ActionEvent actionEvent) {
    // do your stuff here...
    if (ok) {
        RequestContext.getCurrentInstance().addCallbackParam("saved", true);
    } else {
        RequestContext.getCurrentInstance().addCallbackParam("saved", false);
    }
}

надеюсь, это кому-то поможет :)

С помощью oncomplete атрибут из вашей командной кнопки и действительно простой скрипт поможет вам много.

ваша кнопка диалога и команды будет чем-то похожим на это:

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

сценарий будет что-то вроде этого:

<script type="text/javascript">
    function handleDialogSubmit(xhr, status, args) {
        if (args.validationFailed) {
            dialog.show();
        } else {
            dialog.hide();
        }
    }
</script>

Я использую такое решение:

код JSF:

<p:dialog ... widgetVar="dlgModify" ... >
...
<p:commandButton value="Save" update="@form" actionListener="#{AdminMB.saveTable}" />
<p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/>

бэк бин код:

public void saveTable() {
    RequestContext rc = RequestContext.getCurrentInstance();
    rc.execute("PF('dlgModify').hide()");
}

Я считаю, что это самое чистое решение. Делая это вы не нужно менять код кнопки. Это решение переопределяет прототип функции 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();
    };
});

таким образом, вы можете сохранить ваш код:

<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();" 
   actionListener="#{videoBean.saveVideo(video)}" />

самое простое решение-не иметь никакого "виджета".скрыть", ни в onclick, ни в oncomplete. Удалите функции скрытия и просто поместите

visible="#{facesContext.validationFailed}" 

для диалогового теге