我是JSF和primefaces的新手。我正在使用Primefaces对话框架来弹出模态的服务协议条款。我遇到的问题是,当对话框关闭时,我的dialogReturn事件处理程序不会被调用,并且虽然对话框本身关闭,但模态覆盖仍保留在页面上。模态叠加可能是红色鲱鱼,因为当对话框不是模态时,不会调用dialogReturn方法。
以下是相关的代码:
创建对话框的表单:
<h:form prependId="false">
<ul>
<ui:repeat value="#{serviceEditor.service.subsystems}" var="ss">
<li>
<em>#{ss.name}</em> - #{ss.description}<br/>
<ui:fragment rendered="#{identity.loggedIn}">
<ui:fragment rendered="#{grantManager.hasAccess(ss)}">
(You have access to this dataset.)
<h:commandButton value="Discontinue Access" action="#{grantManager.unrequestAccess(ss)}"/>
</ui:fragment>
<ui:fragment rendered="#{!grantManager.hasAccess(ss)}">
<p:commandButton value="Request Access"
actionListener="#{serviceDialog.display(ss)}"
styleClass="btn btn-primary" >
<p:ajax event="dialogReturn"
listener="#{serviceEditor.acceptDialogHandler}" />
</p:commandButton>
</ui:fragment>
...
ServiceEditor已注释@Named @Stateful @ConversationScoped
对话框显示的actionListener代码:
public void display (ServiceSubsystem sub)
{
if (sub == null)
{
log.error("Service Accept dialog attempt with null subservice. Lose.");
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Subservice Unavailable", "We seem to have misplaced that service. This has been logged for investigation.");
RequestContext.getCurrentInstance().showMessageInDialog(message);
return;
}
log.info("svcDlg: Displaying accept dialog for service: {}.{}", sub.getService().getName(), sub.getName());
this.sub = sub;
Map<String, Object> dlgOpts = new HashMap<>(2);
dlgOpts.put("modal", true);
RequestContext.getCurrentInstance().openDialog("serviceAcceptDialog", dlgOpts, null);
log.info("svcDlg: Did that accept dialog work out?");
}
对话框中的accept命令按钮的actionListener代码:
public void accept ()
{
log.info("Accepted {}.{}", sub.getService().getName(), sub.getName());
...
String destination = "/service?faces-redirect=true&uuid=" + sub.getService().getUuid();
log.info("Sending user to: {}", destination);
RequestContext.getCurrentInstance().closeDialog(destination);
}
最后,对话框返回未调用的侦听器:
public void acceptDialogHandler (SelectEvent event)
{
String dest = (String) event.getObject();
log.info("Service accept dialog closed. sending here: ", dest);
((ConfigurableNavigationHandler) FacesContext.getCurrentInstance().getApplication().getNavigationHandler())
.performNavigation(dest);
}
我在文档中遗漏了什么?或者这是一个错误吗?
答案 0 :(得分:1)
我认为您可以尝试使用primefaces dialog component,更简单。
要显示或关闭对话框,您只需要调用它:
PF('widgetVarDialogName').hide();
PF('widgetVarDialogName').show();
您可以在查看操作中打开或关闭它,例如:
<p:commandButton
value="Open dialog"
type="button"
onclick="PF('widgetVarDialogName').show()" />
<p:commandButton
value="Do Action"
action="#{myBean.myAction()}"
oncomplete="PF('widgetVarDialogName').hide();" />
另外,如果需要,可以从bean调用它。
RequestContext.getCurrentInstance().execute("PF('widgetVarDialogName').show()");
RequestContext.getCurrentInstance().execute("PF('widgetVarDialogName').hide()");
(请记住,对话框必须放在表单中)
答案 1 :(得分:0)
我看到你使用rendered="..."
属性做了很多工作。根据我的经验,<p:ajax event="dialogReturn" />
如果没有呈现自身或父元素,则不会被触发。
请查看public void accept()
方法。如果更改某个状态,以便<p:ajax event="dialogReturn" />
的父元素(即rendered="#{!grantManager.hasAccess(ss)}"
和/或rendered="#{identity.loggedIn}"
的呈现的attirbute将评估为false
,则不会执行该侦听器
修改强>
我想到了一个解决方法。可以使用相同的解决方法来避免问题,就像您想要从<p:menuitem />
(Primefaces Dialog Framework — dialogReturn event from menuitem)触发对话框架一样。
只需在可能未渲染的区域之外的某处创建一个单独的按钮,然后通过javascript触发它。
未经测试的代码示例:
<ui:fragment
id="fragment"
rendered="#{...}">
<h:commandButton
id="pseudo_button"
value="..."
onclick="document.getElementById('real_button').click()" />
</ui:fragment>
<h:commandButton
id="real_button"
action="#{bean.realWorkHere()}"
update="fragment"
style="display:none;">
<p:ajax
event="dialogReturn"
listener="#{...}" />
</h:commandButton>