ADF af:showPrintablePageBehavior将所有后续导航命令发送到新窗口

时间:2015-05-18 19:06:38

标签: java oracle-adf

我有一个打印图标,用于呈现表单的可打印版本。

<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>。错失行为与这些方法中的每一种都是一致的。

2 个答案:

答案 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属性中引用该方法。

这里的诀窍是,在实际返回导航结果之前,我们将更改outputModeprintableBehaviorBean属性的值。请注意,此新值将覆盖现有的<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"/>