使用ViewScoped在页面之间导航

时间:2014-05-05 13:18:22

标签: jsf jsf-2

我在数据表中有一个Primefaces命令链接,当单击它时,调用Managed Bean(ViewScoped)中的一个方法,该方法重定向到另一个页面。在此命令链接中,我调用填充将在命运页面中使用的属性。但是,在此命运页面中,属性为null。

导航规则:

<navigation-rule>
    <display-name>pages/proprietario/index.xhtml</display-name>
    <!-- Origin page -->
    <from-view-id>/pages/proprietario/index.xhtml</from-view-id> 
    <navigation-case>
        <!-- Managed bean method -->            
        <from-action>#{proprietarioMB.doPrepareCadastro}</from-action>  
        <from-outcome>cadastro</from-outcome>
        <!-- Destiny page -->
        <to-view-id>/pages/proprietario/cadastro.xhtml</to-view-id>
    </navigation-case>
</navigation-rule>

原始页面中的命令链接

<p:dataTable id="tblResultados"
    value="#{proprietarioMB.proprietarios}" var="proprietario">

    <p:commandLink id="lnkEditar" value="#{msg['titulo.visualizar']}"
        title="#{msg['titulo.visualizar']}"
        action="#{proprietarioMB.doPrepareCadastro}">
            <f:setPropertyActionListener
            target="#{proprietarioMB.proprietario}" value="#{proprietario}" />
    </p:commandLink>

</p:dataTable>

Managed Bean

@ManagedBean
@ViewScoped
public class ProprietarioMB extends BaseMB {

    private List<ProprietarioORM> proprietarios;
    private ProprietarioORM proprietario;

    public String doPrepareCadastro() {
        System.out.println("ProprietarioMB.doOpenDialogoProprietario(): "
                + this.proprietario);

        return "cadastro";
    }

}

命运页面

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<ui:composition template="/template/template.xhtml">
    <ui:define name="header">#{msg['proprietario.titulo.cadastro']}</ui:define>
    <ui:define name="content">
        <h:form id="formPrincipal">
            <br />
            <h:outputText value="#{proprietarioMB.proprietario}" />
        </h:form>
    </ui:define>
</ui:composition>
</html>

给我的一个替代方法是在commandLink内部和命运页面中使用。或多或少,如ViewParam vs @ManagedProperty(value = "#{param.id}")所示。这样,代码更改如下:

原始页面中的命令链接

<p:dataTable id="tblResultados"
    value="#{proprietarioMB.proprietarios}" var="proprietario">

    <h:link id="lnkEditar" value="#{msg['titulo.visualizar']}"
        title="#{msg['titulo.visualizar']}" outcome="contrato" >
            <f:param name="idProprietario" value="#{proprietario.id}" />
    </p:commandLink>

</p:dataTable>

命运页面

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<ui:composition template="/template/template.xhtml">
    <f:metadata>
        <f:viewParam name="idProprietario" value="#{proprietarioMB.idProprietario}" />
    </f:metadata>
    <ui:define name="header">#{msg['proprietario.titulo.cadastro']}</ui:define>
    <ui:define name="content">
        <h:form id="formPrincipal">
            <br />
            <h:outputText value="#{proprietarioMB.proprietario}" />
        </h:form>
    </ui:define>
</ui:composition>
</html>

Managed Bean

@ManagedBean
@ViewScoped
public class ProprietarioMB extends BaseMB {

    private Long idProprietario;
    private ProprietarioORM proprietario;

    public setIdProprietario(Long id) {
        this.idProprietario = id;
        if(id != null) {
            // load proprietario
        }
    }

}

我的问题是,如果这是更好的选择,或者是否有更好的选择。

谢谢,

Rafael Afonso

2 个答案:

答案 0 :(得分:1)

如果您要从一个视图范围页面导航到另一个视图范围页面并且想要将少量参数传递到第二页,最好的方法是使用flash(不是adobe flash)。从页面传递flash中的对象,如下所示。

public String cbCallNewPageClicked() {

        table.getDataTableBinding().reset();
        Flash flash = FacesContext.getCurrentInstance().                
                 getExternalContext().getFlash();          
        flash.put("tableBind", table.dataTableBinding);             
        flash.put("tableRow", table.dtos);            
        flash.put("tableName", table.tableName);
        flash.keep("tableBind");
        flash.keep("tableRow");
        flash.keep("tableName");
    JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),  "openWindow('page2.jsf')");
    return null;
}

在目标bean中获取flash中传递的值,如下所示

public void setFlash(ComponentSystemEvent event){
      Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
      DataTable newBinding = (DataTable) flash.get("tableBind");
      List newTblRow = (List) flash.get("tableRow");
      String tableHead =    (String) flash.get("tableName");

}

从prerenderView事件调用setFlash (将以下行放在facelet中以在页面加载时调用setFlash方法)

<f:event listener="#{page2Bean.setFlash}" type="preRenderView" />

答案 1 :(得分:0)

您描述的第一种方法是使用 POST 请求进行普通页面到页面导航。这是特别气馁。无论如何,您在代码中使用了冗余导航规则。由于JSF 2允许您使用隐式导航,因此在操作方法中返回cadastro结果将指示您在 POST 之后/pages/proprietario/cadastro.xhtml

第二种方式要好得多,事实上要走的路。使用h:link,对目标网页执行 GET 请求。这样您就可以避免在原始bean中执行不必要的代码,同时还指定要在URL中使用的视图参数,使您的导航可收藏并可重复使用。

另见: