Оставьте 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 каким-то образом препятствовал закрытию диалога, если была какая-то проблема, и выводил сообщение только через рычание. Это тот случай, когда валидатор не поможет, потому что нет способа узнать, допустимо ли someValue, пока сохранение не будет отправлено на внутренний сервер. В настоящее время я делаю это с помощью атрибута visible и указываю на логическое поле в mbean. Это работает, но замедляет пользовательский интерфейс, потому что всплывающее или закрывающее диалоговое окно требует попадания на сервер.
6 ответов
onsuccess
запускается, если сам запрос ajax был успешным (т. е. нет сетевых ошибок, необработанных исключений и т. д.), а не в случае успешного вызова метода действия.
Учитывая <p:dialog widgetVar="testDialog">
Вы можете удалить onsuccess
и заменить его на PrimeFaces RequestContext#execute()
внутри saveMethod()
:
if (success) {
RequestContext.getCurrentInstance().execute("PF('testDialog').hide()");
}
Замечания: PF()
был представлен в PrimeFaces 4.0. В старых версиях PrimeFaces вам нужно testDialog.hide()
вместо.
Если вы предпочитаете не загромождать контроллер скриптами, относящимися к представлению, вы можете использовать oncomplete
вместо этого, который предлагает args
объект, который имеет логическое значение validationFailed
имущество:
<p:commandButton ...
oncomplete="if (args && !args.validationFailed) PF('testDialog').hide()" />
if (args)
проверка необходима, потому что она может отсутствовать при возникновении ошибки ajax и, таким образом, вызывать новую ошибку JS при попытке получить validationFailed
от него; &
вместо &
является обязательным по причине, описанной в этом ответе, рефакторинг при необходимости для функции JS, которую вы вызываете, как oncomplete="hideDialogOnSuccess(args, testDialog)"
как показано в Keep
Это последнее решение (с небольшим переписыванием) должно работать для простого jsf h:commandButton
в сочетании с f:ajax
К сожалению, PrimeFaces не поддерживает то, что RichFaces уже поддерживает: переоценка EL во время запроса on*
атрибутов. В противном случае вы также можете сделать это:
<p:commandButton ...
oncomplete="if (#{not facesContext.validationFailed}) PF('testDialog').hide()" />
Я только что нашел это решение. По сути, идея состоит в том, чтобы использовать actionListener вместо действия кнопки, и в компоненте поддержки вы добавляете параметр обратного вызова, который затем проверяет метод oncomplete кнопки. Пример частичного кода:
JSF первый:
<p:commandButton actionListener="#{myBean.doAction}"
oncomplete="if (!args.validationFailed && 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()");
}
Самое простое решение состоит в том, чтобы не иметь никакого "widget.hide", ни в onclick, ни в oncomplete. Удалите функции скрытия и просто поставьте
visible="#{facesContext.validationFailed}"
для тега диалога
Я считаю, что это самое чистое решение. Для этого вам не нужно менять код кнопок. Это решение переопределяет прототип функции 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)}" />