Component eg: MasterDetail does not work on dynamic pages

5

I'm developing a web application that aims to work like Facebook. During browsing the page is not reloaded, loading via AJAX only the central content.

I'm using PrimeFaces 4.0 and PrimeFaces Extension 1.2.1

But when my page (from the central content) contains pe: masterDetail it causes an error on the server

The error is this:

Severe:   Error Rendering View[/index.xhtml]
java.lang.NullPointerException
        at org.primefaces.extensions.component.masterdetail.MasterDetailRenderer.getMenuItemByLevel(MasterDetailRenderer.java:284)
        at org.primefaces.extensions.component.masterdetail.MasterDetailRenderer.updateBreadcrumb(MasterDetailRenderer.java:208)
        at org.primefaces.extensions.component.masterdetail.MasterDetailRenderer.renderBreadcrumb(MasterDetailRenderer.java:186)
        at org.primefaces.extensions.component.masterdetail.MasterDetailRenderer.encodeMarkup(MasterDetailRenderer.java:138)
        at org.primefaces.extensions.component.masterdetail.MasterDetailRenderer.encodeEnd(MasterDetailRenderer.java:101)
        at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)

I created a simple page to simulate the error that happens in my application:

Index.xhtml:

<!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:p="http://primefaces.org/ui">

    <h:head>
        <title>Test</title>
    </h:head>
    <h:body >
        <h:form>
            <p:commandButton action="#{theBean.goToPage('masterDetailPage.xhtml')}" update=":centerContent"/>
        </h:form>

        <h:form id="centerContent">
            <ui:include src="#{theBean.page}"/>
        </h:form>    


    </h:body>
</html>

TheBean.java:

package br.edu.utfpr.projetoteste;

import java.io.IOException;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class TheBean implements Serializable {

    private static final long serialVersionUID = 1L;

    String page = "test.xhtml"; //Simple blank page for this test

    public TheBean() {
    }

    public String getPage() {
        return page;
    }

    public void setPage(String page) {
        this.page = page;
    }

    public void goToPage(String page) throws IOException {
        this.setPage(page);
    }
}

masterDetailPage.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition 
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:pe="http://primefaces.org/ui/extensions">


    <pe:masterDetail id="masterDetail" >

        <pe:masterDetailLevel level="1" levelLabel="Master">
            Test
        </pe:masterDetailLevel >
        <pe:masterDetailLevel level="2" levelLabel="Detail">
            Test
        </pe:masterDetailLevel>


    </pe:masterDetail>


</ui:composition>

When I reload the page via F5, the central content loads right without causing an error.

What I checked out via Debug is that BreadCrumb gets null the first time it runs updateBreadcrumb (), and gets value when it reloads the page.

But I do not want to reload the page. How do I make it work if the page fragment is loaded via AJAX?

    
asked by anonymous 01.02.2014 / 03:07

2 answers

0

There is a solution to this:

Instead of putting a form to give Update, put a h: panelGroup:

<h:body >
    <h:form>
        <p:commandButton action="#{theBean.goToPage('masterDetailPage.xhtml')}" update=":centerContent"/>
    </h:form>

    <h:panelGroup id="centerContent">
        <ui:include src="#{theBean.page}"/>
    </h:panelGroup>    

</h:body>

and within the page that has the MasterDetail put 1 form:

<ui:composition 
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
    xmlns:pe="http://primefaces.org/ui/extensions">

    <h:form>
        <pe:masterDetail id="masterDetail" >

            <pe:masterDetailLevel level="1" levelLabel="Master">
                Test
            </pe:masterDetailLevel >
            <pe:masterDetailLevel level="2" levelLabel="Detail">
                Test
            </pe:masterDetailLevel>


        </pe:masterDetail>
    </h:form>
</ui:composition>

I hope to have helped those who had the same problem as me ...

    
15.02.2014 / 17:12
0

Try to put the

    <h:form>
        <p:commandButton action="#{theBean.goToPage('masterDetailPage.xhtml')}" update=":centerContent"/>
    </h:form>

    <h:form id="centerContent">
        <ui:include src="#{theBean.page}"/>
    </h:form>   

dendro of another form, for example:

<h:form>
    <h:form>
        <p:commandButton action="#{theBean.goToPage('masterDetailPage.xhtml')}" update=":centerContent"/>
    </h:form>

    <h:form id="centerContent">
        <ui:include src="#{theBean.page}"/>
    </h:form>  
</h:form>

Then remove the colon ":" from

update=":centerContent"

Getting only

update="centerContent"

To use update with id the button must be in the same form as the component you need to update.

If it still does not work, you can try replacing the

<h:form>
    <p:commandButton action="#{theBean.goToPage('masterDetailPage.xhtml')}" update=":centerContent"/>
</h:form>

For only

    <p:commandButton action="#{theBean.goToPage('masterDetailPage.xhtml')}" update=":centerContent"/>

Try there and send the test result.

Here is an example of a project I did and it worked out the AJAX part:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets">

<ui:composition template="/resources/templates/interna.xhtml">
    <ui:define name="corpo">               
        <h:form id="meio">

                    <h:panelGrid columns="2">   
                        <h:form id="edicao">
                            <p:panelGrid columns="6">
                                <f:facet name="header">Cadastro/Ediçao de Obras</f:facet>
                                <h:outputLabel value="Solid:" for="txt_solid"></h:outputLabel>  
                                <p:inputText id="txt_solid" value="#{obrasBean.obras.solid}" required="true" label="ID de solicitação Embratel.">
                                    <f:validateLength minimum="1" maximum="11" />
                                </p:inputText>
                                <h:outputLabel value="Nome:" for="txt_nome"></h:outputLabel>  
                                <p:inputText id="txt_nome" value="#{obrasBean.obras.nome}" required="true" label="Nome do cliente">
                                    <f:validateLength minimum="1" maximum="50" />
                                </p:inputText>  
                                <h:outputLabel value="CNL da cidade:" for="txt_cnl"></h:outputLabel>  
                                <p:inputText id="txt_cnl" value="#{obrasBean.obras.cnl}" required="true" label="CNL da Cidade. Ex: Curitiba = CTA" size="4">
                                    <f:validateLength minimum="3" maximum="4" />
                                </p:inputText>
                                <h:outputLabel value="Endereço:" for="txt_end"></h:outputLabel>  
                                <p:inputText id="txt_end" value="#{obrasBean.obras.end}" required="true" label="Endereço. EX: R dos Loucos, 0">
                                    <f:validateLength minimum="1" maximum="60" />
                                </p:inputText>  
                            </p:panelGrid>
                        </h:form>
                        <p:commandButton value="Salvar" action="#{obrasBean.salvar}" style="margin:10px 0" id="btnAdd" update="edicao,listagem" icon="ui-icon-disk" />  
                    </h:panelGrid>
            <!--<h:messages/>-->
            <h:form id="listagem">
                <p:dataTable value="#{obrasBean.lista}" var="obra"  rules="rows" cellpadding="5" paginator="true" rowsPerPageTemplate="5,10,15,20">
                    <f:facet name="caption">
                        A listagem abaixo exibe a relação de todas as obras
                    </f:facet>
                    <f:facet name="header">Fila de Obras</f:facet>
                    <f:facet name="footer">Final da listagem</f:facet>
                    <p:column style="width:16px">  
                        <p:rowToggler />  
                    </p:column>
                    <p:column>
                        <f:facet name="header">Solid</f:facet>
                        <h:outputText value="#{obra.solid}" />
                    </p:column>
                    <p:column>
                        <f:facet name="header">Nome</f:facet>
                        <h:outputText value="#{obra.nome}" />
                    </p:column>
                    <p:column>
                        <f:facet name="header">Cidade</f:facet>
                        <h:outputText value="#{obra.cnl}" />
                    </p:column>
                    <p:column>
                        <f:facet name="header">Endereço</f:facet>
                        <h:outputText value="#{obra.end}" />
                    </p:column>
                    <p:column>
                        <f:facet name="header">Data</f:facet>
                        <h:outputText value="#{obra.data}">
                            <f:convertDateTime dateStyle="medium"/>
                        </h:outputText>
                    </p:column>
                    <p:column>
                        <h:commandButton action="#{obrasBean.excluir}" onclick="if (!confirm('Confirma a exclusão da Obra #{obra.nome}?')) return false;" 
                                             title="Excluir" image="/resources/png/16x16/delete.png">
                            <f:ajax execute="@this" render="@form" />
                                <f:setPropertyActionListener target="#{obrasBean.obras}" value="#{obra}"/>
                        </h:commandButton>
                    </p:column>

                </p:dataTable>

            </h:form>
        </h:form>
    </ui:define>        
</ui:composition>

Notice that there is a meio form that includes two other form edicao and listagem . The commandButton is out of edica and listagem within meio and when you click on commandButton it saves the work and updates listagem .

    
05.02.2014 / 13:56