简体   繁体   English

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

[英]ADF af:showPrintablePageBehavior sends all subsequent navigation commands to a new window

I have a print icon that renders the printable version of the form. 我有一个打印图标,呈现表单的可打印版本。

<af:link id="printButton" icon="/images/printer.png">
   <af:showPrintablePageBehavior/>
</af:link>

This part works properly, but after you close the tab created by the <af:showPrintablePageBehavior/> any attempts to redirect to a new page creates a new browser tab. 这部分工作正常,但在关闭<af:showPrintablePageBehavior/>创建的选项卡后,任何重定向到新页面的尝试都会创建一个新的浏览器选项卡。

The button doing the redirect is defined thusly, 这样定义了执行重定向的按钮,

<af:button text="Search" action="#{backing.searchAction}" 
           partialSubmit="false" immediate="true" id="ab1" />

public String searchAction() {
    return "search" 
}

"search" is a navigation-rule, which is defined in the faces-config.xml and works properly if you do not invoke <af:showPrintablePageBehavior/> before clicking the button. "search"是一个导航规则,它在faces-config.xml定义,如果在单击按钮之前未调用<af:showPrintablePageBehavior/> ,则可以正常工作。

I have tried using ExternalContext.redirect(page) . 我尝试过使用ExternalContext.redirect(page) I have also tried defining the targetFrame attribute to _self and _parent for the <af:button> . 我也尝试将targetFrame属性定义为_self_parent<af:button> The miss-behavior is consistent with each of these approaches. 错失行为与这些方法中的每一种都是一致的。

The root of all evil in your example is the immediate="true" attribute. 你的例子中所有邪恶的根源是immediate="true"属性。 If you just remove it, you'll get your problem solved. 如果您只是删除它,您将解决您的问题。

However, in order to explain why, let's first start with the <af:showPrintablePageBehaviour> component and the trinidad-config.xml file (which is nested within the WEB-INF folder). 但是,为了解释原因,我们首先从<af:showPrintablePageBehaviour>组件和trinidad-config.xml文件(嵌套在WEB-INF文件夹中)开始。

The trinidad-config.xml file lists an element, called <output-mode> . trinidad-config.xml文件列出了一个名为<output-mode>的元素。 By default, it's not there, but you can add it manually. 默认情况下,它不存在,但您可以手动添加它。 The element supports three values: 该元素支持三个值:

  • "default" (or null ): the default output mode "default" (或null ):默认输出模式
  • "printable" : an output mode suitable for printable pages "printable" :适用于可打印页面的输出模式
  • "email" : an output mode suitable for e-mailing a page's content "email" :适用于通过电子邮件发送页面内容的输出模式

In order to have a page content displayed as a printable, the output-mode is changed (usually by the underlying framework) to "printable" . 为了使页面内容显示为可打印, output-mode (通常由底层框架)更改为"printable" So, every time you click on your <af:link> component, the <output-mode> value is set to "printable" . 因此,每次单击<af:link>组件时, <output-mode>值都将设置为"printable"

The good thing about trinidad-config.xml is that we are allowed to use EL expressions within, which means that we can dynamically change the value of the <output-mode> element. trinidad-config.xml的好处是我们可以在其中使用EL表达式,这意味着我们可以动态地改变<output-mode>元素的值。 For example, the value can be read from a @ManagedBean : 例如,可以从@ManagedBean读取值:

 <output-mode>#{printableBehaviorBean.outputMode}</output-mode>

The been itself can be a completely simple ( @RequestScoped ) bean. 本身可以是一个完全简单的( @RequestScoped )bean。 Note that I'm using annotations instead of XML-based configuration, because you mentioned you're using ADF 12c, which is built on the top of JSF-2. 请注意,我使用的是注释而不是基于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;
    }
}

Then, we can inject this bean within another bean, which will help us navigate to the "search" activity when the Search button is pressed. 然后,我们可以注入另一个bean,这将有助于我们定位到内这个bean "search"的活动时, Search按钮被按下。 The bean will have a nested @ManagedProperty member, which will hold an instance of the preceding printableBehaviorBean bean. 该bean将有一个嵌套的@ManagedProperty成员,该成员将保存前面的printableBehaviorBean bean的实例。 Also, the navigationBean will introduce a search() method, which we'll be referred from the Search button's action attribute. 此外, navigationBean将引入一个search()方法,我们将从Search按钮的action属性中引用它。

The trick here's that before actually returning the navigation outcome, we'll change the value of the outputMode property in the printableBehaviorBean . 这里的诀窍是,在实际返回导航结果之前,我们将更改printableBehaviorBean outputMode属性的值。 Remember that this new value will overwrite the existing <output-mode> value and if the <output-mode> value was previously set to "printable" , it will be reverted back to "default" (and this will happen every time we click the on Search button). 请记住,这个新值将覆盖现有的<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";
    }

}

And finally, the Search button definition would be changed slightly to: 最后, Search按钮定义将略微更改为:

<af:button text="Search" action="#{navigationBean.search}" immediate="true" id="ab1" />

Now, another question of interest would be "Why removing immediate="true" solves the problem? . 现在,另一个感兴趣的问题是“为什么删除immediate="true"解决问题?

A UICommand component decorated with immediate="true" will make the framework skip the "Process validations", "Update model values" and "Invoke application" JSF life-cycle phases (ie the 3rd, 4th and the 5th phase). immediate="true"装饰的UICommand组件将使框架跳过“过程验证”,“更新模型值”和“调用应用程序”JSF生命周期阶段(即第3,第4和第5阶段)。 My assumption on your problem would be that before the "Invoke application" phase, the ADF implementation checks if the command components is decorated with a <af:showPrintablePageBehaviour> component and if it is, then it programmatically changes the value of the <output-mode> element. 我对你的问题的假设是,在“调用应用程序”阶段之前,ADF实现检查命令组件是否用<af:showPrintablePageBehaviour>组件装饰,如果是, <af:showPrintablePageBehaviour>编程方式更改<output-mode>的值<output-mode>元素。 And since you have immediate="true" on the "Search" button, this value would be left as "printable" . 由于您在"Search"按钮上有immediate="true" ,因此该值将保留为"printable" That's why when you go back to the form, it triggers a new tab. 这就是为什么当你回到表单时,它会触发一个新选项卡。

So, in conclusion, either remove the immediate="true" attribute, or follow the workaround with the beans I suggested. 因此,总之, 要么删除immediate="true"属性, 要么使用我建议的bean遵循变通方法。

由于你使用ADF 12c和Konstantin Yovkov描述了这个问题,也许你可以删除inmediate属性并放入af:button

<af:target events="@all" execute="@this" render="@all"/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM