【问题标题】:Navigation between pages with ViewScoped使用 ViewScoped 在页面之间导航
【发布时间】:2014-06-21 19:36:56
【问题描述】:

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

导航规则:

<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>

托管豆

@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>

托管豆

@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
        }
    }

}

我的问题是这是更好的选择还是有更好的选择。

谢谢,

拉斐尔·阿方索

【问题讨论】:

  • 感觉很难看代码。你能解释更多吗?

标签: jsf jsf-2


【解决方案1】:

如果您从一个视图范围页面导航到另一个页面,并且您想将几个参数传递到第二个页面,最好的方法是使用 flash(不是 adobe flash)。从 from 页面传递 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" />

【讨论】:

    【解决方案2】:

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

    第二种方法要好得多,实际上是要走的路。使用h:link 对目标页面执行GET 请求。这样可以避免在原始 bean 中执行不必要的代码,同时您还可以指定要在 url 中使用的视图参数,从而使您的导航可收藏和可重用。

    另请参阅:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多