我有一个打印图标,用于呈现表单的可打印版本。
<af:link id="printButton" icon="/images/printer.png">
<af:showPrintablePageBehavior/>
</af:link>
此部分正常运行,但在您关闭<af:showPrintablePageBehavior/>
创建的标签后,任何重定向到新页面的尝试都会创建一个新的浏览器标签。
这样定义了执行重定向的按钮,
<af:button text="Search" action="#{backing.searchAction}"
partialSubmit="false" immediate="true" id="ab1" />
public String searchAction() {
return "search"
}
"search"
是导航规则,在faces-config.xml
中定义,如果在单击按钮之前未调用<af:showPrintablePageBehavior/>
,则可以正常工作。
我尝试过使用ExternalContext.redirect(page)
。我还尝试为targetFrame
定义_self
属性,为_parent
定义<af:button>
。错失行为与这些方法中的每一种都是一致的。
答案 0 :(得分:5)
示例中所有邪恶的根源是immediate="true"
属性。如果您只是删除它,您将解决问题。
但是,为了解释原因,我们首先从<af:showPrintablePageBehaviour>
组件和trinidad-config.xml
文件(嵌套在WEB-INF
文件夹中)开始。
trinidad-config.xml
文件列出了一个名为<output-mode>
的元素。默认情况下,它不存在,但您可以手动添加它。该元素支持三个值:
"default"
(或null
):默认输出模式"printable"
:适合可打印页面的输出模式"email"
:适合通过电子邮件发送网页内容的输出模式为了使页面内容显示为可打印,output-mode
会更改(通常由底层框架)到"printable"
。因此,每次点击<af:link>
组件时,<output-mode>
值都会设置为"printable"
。
关于trinidad-config.xml
的好处是我们可以在其中使用EL表达式,这意味着我们可以动态地更改<output-mode>
元素的值。例如,可以从@ManagedBean
:
<output-mode>#{printableBehaviorBean.outputMode}</output-mode>
本身可以是一个完全简单的(@RequestScoped
)bean。请注意,我使用的是注释而不是基于XML的配置,因为您提到使用的是ADF 12c,它建立在JSF-2的顶层。
@RequestScoped
@ManagedBean(name = "printableBehaviorBean")
public class PrintableBehaviorBean {
private String outputMode;
public void setOutputMode(String outputMode) {
this.outputMode = outputMode;
}
public String getOutputMode() {
return outputMode;
}
}
然后,我们可以在另一个bean中注入这个bean,这将帮助我们在按下"search"
按钮时导航到Search
活动。 bean将有一个嵌套的@ManagedProperty
成员,它将保存前面的printableBehaviorBean
bean的一个实例。此外,navigationBean
会引入search()
方法,我们将从Search
按钮的action
属性中引用该方法。
这里的诀窍是,在实际返回导航结果之前,我们将更改outputMode
中printableBehaviorBean
属性的值。请注意,此新值将覆盖现有的<output-mode>
值,如果<output-mode>
值之前已设置为"printable"
,则会将其恢复为"default"
(这将发生每次我们点击Search
按钮。
@RequestScoped
@ManagedBean(name = "navigationBean")
public class NavigationBean {
@ManagedProperty(name = "printableBehaviorBean", value="#{printableBehaviorBean}")
private PrintableBehaviorBean printableBehaviorBean;
public void setPrintableBehaviorBean(PrintableBehaviorBean printableBehaviorBean) {
this.printableBehaviorBean = printableBehaviorBean;
}
public PrintableBehaviorBean getPrintableBehaviorBean() {
return printableBehaviorBean;
}
public String search() {
printableBehaviorBean.setOutputMode("default");
return "search";
}
}
最后,Search
按钮定义会略微改为:
<af:button text="Search" action="#{navigationBean.search}" immediate="true" id="ab1" />
现在,另一个感兴趣的问题是“为什么要删除immediate="true"
解决问题?。
用UICommand
装饰的immediate="true"
组件将使框架跳过“过程验证”,“更新模型值”和“调用应用程序”JSF生命周期阶段(即第3个,第4个和第3个第五阶段)。我对您的问题的假设是,在“调用应用程序”阶段之前,如果命令组件使用<af:showPrintablePageBehaviour>
组件进行修饰,则ADF实现检查,如果是,则以编程方式更改<output-mode>
元素的值。由于immediate="true"
按钮上有"Search"
,因此此值将保留为"printable"
。这就是为什么当你回到表单时,它会触发一个新选项卡。
因此,总而言之, 删除immediate="true"
属性,或按照我建议的bean进行解决。
答案 1 :(得分:0)
由于你使用ADF 12c和Konstantin Yovkov描述了这个问题,也许你可以删除inmediate属性并放入af:button
<af:target events="@all" execute="@this" render="@all"/>