Reputation: 615
I have a Primefaces command link inside a datatable that, when clicked, calls a method in Managed Bean (ViewScoped) which redirect to another page. In this command link, I call to fill a property that will be used in destiny page. However, in this destiny page, the property is null.
The navigation rule:
<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>
The command link in origin page
<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>
The 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";
}
}
The Destiny page
<?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>
A alternative that was given to me was use inside commandLink and with in destiny page. More or less as shown in ViewParam vs @ManagedProperty(value = "#{param.id}"). This way, the code is changed as follow:
The command link in origin page
<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>
The Destiny page
<?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>
The 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
}
}
}
My question is if this is the better alternative or if there is better ones.
Thanks,
Rafael Afonso
Upvotes: 0
Views: 1463
Reputation: 31651
The first way you describe is using a POST request for plain page to page navigation. This is specially discouraged. Anyway, you're using redundant navigation rules in your code. As JSF 2 allows you to use implicit navigation, returning cadastro
outcome as you do in your action method will direct you to /pages/proprietario/cadastro.xhtml
after the POST.
Second way is far better, the way to go in fact. With h:link
a GET request is performed to the destination page. This way you avoid executing unecessary code in the origin bean, while you also specify a view parameter to be used in the url, making your navigation bookmarkable and reusable.
See also:
Upvotes: 0
Reputation: 2934
If you are navigating from one view scoped page to another and you wanted to pass few parameters to second page, The best way is to use flash(not adobe flash). From the from page pass the objects in flash as shown below.
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;
}
In the destination bean get the values passed in flash as shown below
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");
}
where setFlash is called from on prerenderView event (put the following line in facelet to call setFlash method on page load)
<f:event listener="#{page2Bean.setFlash}" type="preRenderView" />
Upvotes: 1