Component pe:Masterdetail does not work on dynamic pages

Asked

Viewed 704 times

5

I’m developing a web app that aims to work like Facebook. During the navigation 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 (central content) page contains pe:masterDetail it causes an error on the server

That is the mistake:

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 via F5 to page, the central content loads right, without causing error.

What I checked via Debug is that Breadcrumb is null the first time you run updateBreadcrumb(), and is valued when you reload the page.

But I don’t want to reload the page. How to proceed so that it works in case the page fragment is loaded via AJAX?

2 answers

0


There is a solution to this:

Instead of putting a form to give Update, put an 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 inside the page that has 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 I helped those who had the same problem I did...

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 from 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 two points ":" from

update=":centerContent"

Just staying

update="centerContent"

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

If it still doesn’t work you can try to replace 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 it and send the test results.

Here is an example of a project I did and worked 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>

Note that there is a form meio comprising two other forms edicao and listagem. The commandButton is out of edica and listagem inside the meio and when you click on commandButton it saves the Work and updates the listagem.

  • I used both cases, and the error persists...

  • I edited my answer, take a look there, and put an example. If you take a look at the Primefaces documentation the components should always stay inside a form to function properly. The Primefaces Extension is no different, try to put the pe:masterDetail within a form also.

  • I have other pages that work with AJAX as well, but when you have the component pe:Masterdetail does not work, returning the error that is in the question.

  • But you got to put the components pe:MasterDetail within the form?

  • I did a little different... The solution posted as answer to the question... Thanks anyway @brunowff

Browser other questions tagged

You are not signed in. Login or sign up in order to post.