JSF 2 + Primeface 3 = problema ao selecionar registro em dataTable

4 respostas
Alys

Ola pessoal,

Estou trabalhando em um projeto com JSF2 + Primefaces 3 (primeira vez que uso primefaces), e estou com uma dúvida na utilização de menus de contexto dentro de tabelas.

Estou tentando utilizar o modelo de tabelas+menu deste exemplo.

Porém, estou reparando que a caixa de diálogo carDialog somente aparece corretamente quando a inicialização da lista carsSmall (utilizada no componente p:dataTable) é feita no método construtor, é isso mesmo? (Fiz testes inclusive baixando os fontes e testando aqui na minha máquina). Não entendi por que deve ser assim, se for o caso.

E, neste cenário, eu estaria com um problema maior: preciso mostrar uma tabela com uma lista de pessoas, na qual seja possível visualizar detalhes (não posso colocar tudo dentro da tabela, pois são muitos dados) e alterar endereço e gerar relatórios para cada pessoa. Tudo isso funciona perfeitamente quando inicializo a lista de pessoas dentro do construtor, mas, não sei como faria isso visto que esta lista deve ser inicializada através de um filtro previamente feito em um formulário.

Um pouco de código ajuda a entender o problema, então, vamos lá :-)

Abaixo segue meu bean de pessoa (a propósito, se eu mudar o escopo para session funciona, mas, não acho esta uma solução decente).

@ManagedBean
@RequestScoped
public class PessoaBean implements Serializable {
	
	private Pessoa pessoaSelecionada;
	private String indice;
	private List<pessoa> pessoas;
	private PessoaDataModel modeloPessoas;
	
	public PessoaBean(){
		//Teste
		indice = "ABC"; //forçando o preenchimento do indice
		pessoas = pessoaService.buscaPessoas(indice); //é um web service, está no ar e funcionando corretamente
		modeloPessoas = new pessoaDataModel(pessoas);
	}
	
	public String pesquisar(){
		pessoas = pessoaService.buscaPessoas(indice); //indice desta vez foi preenchido pelo formulario
		modeloPessoas = new pessoaDataModel(pessoas);
		return "listaPessoas";
	}
	
	//demais metodos de negocio
	
	//getters e setters seguem abaixo
}

(minha classe PessoaDataModel está basicamente igual à do exemplo, CarDataModel, foi copy-and-paste mesmo. Basta trocar "Car" por "Pessoa").

Agora, trecho da minha página inicial, que possui apenas um texto de apresentação, e um formulario para digitar o indice ("indice", apesar do nome, é uma forma de categorizar pessoas... é estranho, mas, o modelo de dados é assim, e os usuários entendem assim).

<h:form>

<table width="100%" border="0" cellspacing="0" cellpadding="4"
	class="tableConsulta">
	<tr>
		<td width="100%">
			<fieldset>
				<legend>Busca pessoa</legend>
				<font size="2" face="Arial">Índice:</font>
				<h:inputText id="indice" value="#{pessoaBean.indice}" />
			
			</fieldset>
		</td>
	</tr>
</table>

<h:panelGroup style="display:block; text-align:center">
	<h:commandButton value="Pesquisar" type="submit" action="#{pessoaBean.pesquisar}" />
</h:panelGroup>
</h:form>

E, por fim, tenho o seguinte XHTML para listar as pessoas:

<h:form id="form">

    <p:growl id="growl" showDetail="true"/>

    <p:dialog header="Detalhes do imóvel" widgetVar="pessoaDialog" resizable="false"
                showEffect="explode" hideEffect="explode">

        <h:panelGrid id="display" columns="2" cellpadding="4">

            <h:outputText value="Indice" />
            <h:outputText value="#{pessoaBean.pessoaSelecionada.indice}" />

            <h:outputText value="Nome:" />
            <h:outputText value="#{pessoaBean.pessoaSelecionada.nome}" />

            //demais dados da pessoa
        </h:panelGrid>
    </p:dialog>
    
    <br /><br /><br />
    
    <p:contextMenu for="tpessoas">  
        <p:menuitem value="Detalhes" update="display" icon="ui-icon-search" oncomplete="pessoaDialog.show()"/>  
        <p:menuitem value="Alterar" update="tpessoas" icon="ui-icon-pencil" actionListener="#{pessoaBean.alterar}"/>
        <p:menuitem value="Relatorio XYZ" update="tpessoas" icon="ui-icon-note" actionListener="#{pessoaBean.relatorioXYZ}"/>
        <p:menuitem value="Relatorio QWE" update="tpessoas" icon="ui-icon-note" actionListener="#{pessoaBean.relatorioQWE}"/> 
    </p:contextMenu> 
    
    <p:dataTable id="tpessoas" var="pessoa" value="#{pessoaBean.modeloPessoas}" paginator="true" rows="10"
                 selection="#{pessoaBean.pessoaSelecionada}" selectionMode="single">

        <f:facet name="header">
            Selecione um imóvel
        </f:facet>

        <p:column headerText="Indice">
            #{pessoa.indice}
        </p:column>

        <p:column headerText="Nome">
            #{pessoa.nome}
        </p:column>
        
    </p:dataTable>

</h:form>

Como mencionei antes, este código todo funciona, desde que a lista de pessoas modeloPessoas seja inicializada no construtor. Se eu remover aquele código de teste, os dados na caixa de diálogo pessoaDialog não são preenchidos, todos ficam nulos. Mantendo a inicialização do modeloPessoas no construtor, funciona normalmente (sem alterar mais anda no código).

Como posso fazer então para criar esta tabela a partir de um filtro? Eu tentei até usar dois beans diferentes, um para a primeira tela e outro para a lista, usando um @ManagedProperty para o indíce, mas, ele só é inicializado após a criação do bean, então também não funciona.

Por ultimo: eu tentei fazer isto aqui, mas, dá nullpointer, não acha o componente :-(

Obrigada.

4 Respostas

M

Fala Alys

Ja que vc falou que funcionou com o SessionScoped, porque ao invés de vc usar o Request
vc não tenta usar o @ConversationScoped, que permite que vc inicie ele e feche na hora que vc quiser, Esse escopo é meio que um escopo que vc inicia e fecha na hora que quiser…

Espero ter ajudado…

Falow

Alys

Oi magni,

Obrigada pela resposta.

Antes de comentar, porém, só para registrar: passei no fórum do Primefaces e a sugestão deles mesmo foi usar escopo Sessão :frowning:
Segue link: http://forum.primefaces.org/viewtopic.php?f=3&t=17455

Com relação à sugestão do @ConversationScoped, agradeço muito a dica. Pretendo sim testar este escopo, pois parece bem melhor do que usar Session.

Estava pesquisando sobre o assunto, pelo que entendi essa anotação é um padrão (JSR-299) do Java, ainda não nativo no JSF 2; seria portanto necessária alguma outra biblioteca. Neste exemplo, a implementação de CDI que o autor usa é do Glassfish. No meu caso, uso Tomcat 6, não sei se haveria alguma incompatibilidade. Ainda pelo que vi na minha breve pesquisa, a implementação mais comum seria uma chamada WELD, do Seam? Desculpem a ignorância, mas, ainda não tive oportunidade de usar o Seam. Alguém já trabalhou com ela? Estou lendo a introdução, mas, ainda não entendi muito bem como você controla o início e o fim do escopo. Vi que existe uma opção de timeout, mas, fica por conta do Cointainer.

C

Oii, Alys!

Nesse caso, você pode usar a lista inicialmente sendo vazia ou fazendo uma query padrão, mas que não seja null (O JSF requer que você tenha domínio de toda a camada de controle, inclusive que você instancie os objetos utilizados por ele).

Após preencher o seu filtro da maneira desejada, é só usar o Partial Update (PPR): http://www.primefaces.org/showcase-labs/ui/pprUpdate.jsf
Ao realizar a busca, colocar o id da dataTable no update=“idDaDataTable” do seu p:commandButton.

Desta forma, a sua lista vai ser recarregada por ajax, e preenchida com os novos valores da sua lista! =)

Qualquer dúvida, é só falar!

C

Ah, mas para isso você precisa ter os dois códigos na mesma página…
E pode colocar o filtro em um outputPanel e usar o atributo rendered="#{meuBean.modoEdicao eq false}" para mostrá-lo condicionalmente! =)
De certa forma também dá p/ deixar em dois arquivos, usando o ui:include =)

Criado 9 de janeiro de 2012
Ultima resposta 28 de fev. de 2012
Respostas 4
Participantes 3