想象一下,我有jsf表单和打印表单数据报表的按钮。该按钮需要在新页面上打开数据(目标=空白),但 h:按钮不适合我需要在报告之前保存数据页面打开。因此,我使用 h:commandButton 进行保存操作,然后重定向到报告页面:
<h:commandLink styleClass="reportButton" action="#{polisBean.doReportPrint}"
target="_blank" id="reportListLink">
Print report
</h:commandLink>
@ViewScoped
@Named
public class PolisBean
...
public Object doReportPrint() {
if (canEdit() && this.submit() == null) {
return null;
}
return "printReport";
}
<navigation-case>
<from-outcome>printReport</from-outcome>
<to-view-id>/polises/reportList.xhtml</to-view-id>
<redirect include-view-params="true">
<view-param>
<name>id</name>
<value>#{polis.id}</value>
</view-param>
</redirect>
</navigation-case>
实体保存完好,新页面随报告打开。好。但是当我回到初始表单页面并尝试再次保存时 - 视图已过期并由new构建(因为这不是回发请求,这对JSF来说是一个全新的请求,因为我只是从这个重定向页!)。虽然重定向是在打开第二页时完成的,但这并不能防止丢失所有视图范围的bean数据..
我尝试了来自CDI的长时间运行的 conversationScope ,但当我转回到它时,它会抛出“ContextNotActiveException:WELD-001303范围类型javax.enterprise.context.ConversationScoped没有活动上下文”异常初始页......
有人解决了这个问题吗?如何通过重定向(到新页面)提交表单但不会丢失初始数据?
答案 0 :(得分:2)
如果有人有兴趣,我找到了解决方法。不是很漂亮,但允许使用重定向到“空白”页面:
收据是在新窗口中打开链接后刷新初始页面(参见 onclick ):
<h:commandLink styleClass="reportButton" action="#{polisBean.doReportPrint()}" onclick="window.setTimeout(refreshPage, 2000)"
target="_blank" id="reportListLink" >
print report
</h:commandLink>
但这并不像看起来那么简单,我不能使用简单的location.reload()或类似的smth。在 doReportPrint()方法中,我执行保存操作,如果实体不存在,则创建它。当我对我的应用程序使用GET参数化请求时,我需要使用以下 id 参数的地址刷新页面:
/polises/polis.jsf?id=80
因此,需要完成新的jsf请求,而不是简单的JS刷新,它包含新创建的实体的id。所以我使用这种方法:
在 doReportPrint 中,我将新创建的ID保存到会话中:
public Object doReportPrint() {
if (canEdit() && this.submit() == null) {
return null;
}
context().getExternalContext().getSessionMap().put("justUpdatedPolisId", entity.getId());
return "printReport";
}
初始页面的刷新按以下方式完成:
public Object doRefresh() {
Object justUpdatedPolisId = context().getExternalContext().getSessionMap().get("justUpdatedPolisId");
if (justUpdatedPolisId != null) {
entity.setId((Long)justUpdatedPolisId);
context().getExternalContext().getSessionMap().remove("justUpdatedPolisId");
return "save";
}
// If for some reasons we have not found it - moving to polises table
return "polises?faces-redirect=true";
}
保存结果会导致polis.jsf重新打开(使用faces-config导航),并且ID会自动从 entity.id 附加
另一个技巧是如何从JS调用JSF动作。我试图模仿 h:commandLink 点击(只是为链接复制了生成的JS代码),但这不起作用,因为视图被重新创建并且bean和它的属性相同,操作简单没被叫。所以我在PrimeFaces p:commandLink 中使用了JS代码,它对我很有用(别忘了将“更新”设置为@none并将“处理”设置为@this):
<script type="text/javascript">
function refreshPage() {
PrimeFaces.ajax.AjaxRequest('/KaskoCalculator/polises/polis.jsf',{formId:'polisForm',async:false,global:true,source:'polisForm:doRefresh',process:'polisForm:doRefresh',update:'@none'});
}
</script>
现在,报告保存并在新窗口中打开后,初始页面将在2秒内刷新。太丑了,太累了,但它对我有用。可能会帮助其他人。
答案 1 :(得分:0)
我面临同样的问题。 使用p:commandLink或h:commandLink with target = _blank,初始页面支持bean数据在打开新窗口后消失。
刷新将返回页面的初始状态而不进行ajax更新。但是我需要在点击打印命令之前保持相同的状态。