Сохранять 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 каким-то образом предотвратить закрытие диалога, если возникла какая-то проблема, и выводить сообщение только через рычание. Это случай, когда валидатор не поможет, потому что нет способа узнать, действителен ли какой-либо валид, пока не будет сохранено резервное копирование на задний сервер. В настоящее время я делаю это с использованием видимого атрибута и указываю его на логическое поле в mbean. Это работает, но это делает пользовательский интерфейс более медленным, потому что для всплытия или по диалогу требуется поражение сервера.
Ответы
Ответ 1
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 & lt; p: диалоговое окно & GT; открыть при сбое проверки.
Однако, если нет ошибки валидации и метод действия успешно запущен, и вы все равно хотели бы оставить диалог открытым, например, из-за. исключение в вызове метода службы, затем вы можете вручную вызвать validationFailed
- true
изнутри метода действия вспомогательного компонента, явно вызвав FacesContext#validationFailed()
. Э.Г.
FacesContext.getCurrentInstance().validationFailed();
Ответ 2
Я только что погуглил это решение. По сути, идея состоит в том, чтобы использовать 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);
}
}
Надеюсь, это поможет кому-то :)
Ответ 3
Использование атрибута oncomplete
из вашей командной кнопки и действительно простой script поможет вам многое.
Ваша кнопка диалога и команды будет похожа на это:
<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 будет примерно таким:
<script type="text/javascript">
function handleDialogSubmit(xhr, status, args) {
if (args.validationFailed) {
dialog.show();
} else {
dialog.hide();
}
}
</script>
Ответ 4
Я использую это решение:
Код JSF:
<p:dialog ... widgetVar="dlgModify" ... >
...
<p:commandButton value="Save" update="@form" actionListener="#{AdminMB.saveTable}" />
<p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/>
Резервное копирование bean кода:
public void saveTable() {
RequestContext rc = RequestContext.getCurrentInstance();
rc.execute("PF('dlgModify').hide()");
}
Ответ 5
Я считаю, что это самое чистое решение.
Для этого вам не нужно менять код кнопок.
Это решение переопределяет прототип функции 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)}" />
Ответ 6
Самое простое решение - не иметь никакого "widget.hide", ни в onclick, ни в oncomplete. Удалите скрытые функции и просто поместите
visible="#{facesContext.validationFailed}"
для тега диалога