[Resolvido] Dúvida com o RemoteCommand do primefaces e duplo click

7 respostas
T

Bom dia galera.

Estou com um probleminha na minha aplicação. Vou tentar resumir meu problema em um contexto bem simples.
Tenho uma view matricula.xhtml. Nesta view possuo um data table com minhas matriculas. A idéia inicial é que ao clicar em uma linha desta tabela o jsp renderize um dialog com os dados do objeto da linha que foi clicada. Consegui fazer funcionar isso, porém, não com dois clicks. Ele funcionou apenas com 1 click, o que não é interessante.

Meu outro problema é o seguinte. O usuário poderá clicar em uma linha e ver os dados daquele objeto, editando, ou simplesmente, visualizando. Como também pode cadastrar uma nova matricula apenas clicando no botao novo. O problema é que o selection do meu data table e a instancia que armazena uma nova matricula são a mesma variavel. Tentei fazer o seguinte, caso o usuário click em “novo” eu chamo um função que instanciará uma novo objeto matricula para assim poder persisti-lo no banco, porem não consigo fazer essa chamada no meu codigo. Sempre que tento cadastrar uma nova matricula retorna o erro de que o objeto não foi instanciado (nulo) e se caso antes eu tiver clicado em uma linha do datatable e depois clicado em “novo”, ele carrega os dados da linha e não instancia um novo objeto.

Já tentei resolver isso de varias formas, com remoteCommand, ajax, no proprio commandButton, mas todos sem sucesso. Gostaria da ajuda de vocês!

Obrigado.

Abaixo segue meus codigos:

Matricula.xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.org/ui">

<ui:composition template="/_template.xhtml">

	<ui:define name="corpo">

		<h:form id="formulario">
			
			<h:messages styleClass="erros" />
			
			<h2>Matrículas</h2>

			<fieldset>
			
				<legend>Listagem</legend>
				
				<h:form id="matricula" >
					
					<p:remoteCommand id="novaMatricula" name="novaMatricula" action="#{matriculaBean.novo}" oncomplete="matriculaDialogo.show();" >
						<f:ajax execute=":novaMatricula" />
					</p:remoteCommand>
					
					<p:dataTable id="matriculas" var="matriculas"
						value="#{matriculaBean.matriculas}"
						emptyMessage="Nenhuma matrícula encontrada."
						selectionMode="single"
						selection="#{matriculaBean.matricula}"
						rowKey="#{matriculas.id}" >
												
						<p:ajax event="rowSelect" update=":formulario" 
							oncomplete="matriculaDialogo.show();" />
						
						<p:column id="nome" filterBy="#{matriculas.nome}"
							headerText="Nome">
							<h:outputText value="#{matriculas.nome}" />
						</p:column>
	
						<p:column id="apelido" filterBy="#{matriculas.apelido}"
							headerText="Apelido">
							<h:outputText value="#{matriculas.apelido}" />
						</p:column>
	
						<p:column id="cpf" filterBy="#{matriculas.cpf}" headerText="CPF">
							<h:outputText value="#{matriculas.cpf}" />
						</p:column>
						
						<f:facet name="footer">

							<p:commandButton id="novo" value="Novo" type="button"
								onclick="novaMatricula();"
								ajax="false" >
								<f:ajax execute=":formulario"/>																																
							</p:commandButton>
																										
						</f:facet>						
		
					</p:dataTable>									
		
					<p:dialog id="formularioMatricula" header="Detalhes da Matrícula"
					widgetVar="matriculaDialogo" modal="true" dynamic="true" >
										
					<fieldset>

						<legend>Nova Matricula</legend>

							<h:panelGrid columns="2" >
							
								<h:outputLabel value="Nome:" />
								<p:inputText value="#{matriculaBean.matricula.nome}" size="50" />
	
								<h:outputLabel value="Apelido:" />
								<p:inputText value="#{matriculaBean.matricula.apelido}" />
	
								<h:outputLabel value="Email:" />
								<p:inputText value="#{matriculaBean.matricula.email}" />
	
							</h:panelGrid>
	
							<h:panelGrid columns="4">
	
								<h:outputLabel value="Telefone 1:" />
								<p:inputMask mask="([telefone removido]"
									value="#{matriculaBean.matricula.telefone1}" />
	
								<h:outputLabel value="Telefone 2:" />
								<p:inputMask mask="([telefone removido]"
									value="#{matriculaBean.matricula.telefone2}" />
	
								<h:outputLabel value="Celular 1:" />
								<p:inputMask mask="([telefone removido]"
									value="#{matriculaBean.matricula.celular1}" />
	
								<h:outputLabel value="Celular 2:" />
								<p:inputMask mask="([telefone removido]"
									value="#{matriculaBean.matricula.celular2}" />
	
								<h:outputLabel value="C.P.F:" />
								<p:inputMask mask="[CPF removido]"
									value="#{matriculaBean.matricula.cpf}" />
	
							</h:panelGrid>
	
							<h:panelGrid columns="5">
	
								<h:outputLabel value="Identidade:" />
								<p:inputText value="#{matriculaBean.matricula.identidade}" />
	
								<h:outputLabel value="Orgão Expeditor:" />
								<p:inputText value="#{matriculaBean.matricula.orgaoExpeditor}" />
	
							</h:panelGrid>
	
							<h:panelGrid columns="2">
	
								<h:outputLabel value="Data Expedição:" />
								<p:calendar value="#{matriculaBean.matricula.dataExpedicao}"
									pattern="dd/MM/yyyy" />
	
								<h:outputLabel value="Estado Civil:" />
								<p:selectOneMenu value="#{matriculaBean.idEstadoCivil}">
	
									<f:selectItems value="#{estadoCivilBean.estadosCivis}"
										var="estadocivil" itemValue="#{estadocivil.id}"
										itemLabel="#{estadocivil.descricao}" />
	
								</p:selectOneMenu>
	
								<h:outputLabel value="Nome da Mãe: " />
								<p:inputText value="#{matriculaBean.matricula.nomeMae}" size="50" />
	
								<h:outputLabel value="Nome do Pai: " />
								<p:inputText value="#{matriculaBean.matricula.nomePai}" size="50" />
										
								<p:commandButton value="Salvar"
									action="#{matriculaBean.salvar}" ajax="false" />
									
								<p:commandButton value="Cancelar"
									action="#{matriculaBean.cancelar}" ajax="false" />													
				
							</h:panelGrid>								

					</fieldset>

				</p:dialog>
				
				</h:form>
			
			</fieldset>

		</h:form>

	</ui:define>

</ui:composition>

</html>

MatriculaBean.java

package br.com.enterprisestoq.bean;

import java.io.Serializable;
import java.util.GregorianCalendar;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import br.com.enterprisestoq.dao.DAO;
import br.com.enterprisestoq.dao.MatriculaDAO;
import br.com.enterprisestoq.modelos.EstadoCivil;
import br.com.enterprisestoq.modelos.Matricula;

@ManagedBean
@ViewScoped
public class MatriculaBean implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private List<Matricula> matriculas;
	private Matricula matricula;
	private Matricula novaMatricula = new Matricula();
	private Long idEstadoCivil;
	private DAO<Matricula> dao = new MatriculaDAO();

	public void novo(){		
		System.out.println("instanciando novo objeto matricula....");
		this.matricula = new Matricula();
	}
	
	public String salvar() {
		
		EstadoCivil estadoCivil = new DAO<EstadoCivil>(EstadoCivil.class)
				.buscaPorId(idEstadoCivil);

		this.matricula.setEstadoCivil(estadoCivil);		
		
		if(this.matricula.getId() == null){		
			this.matricula.setDataInclusao(new GregorianCalendar().getTime());					
			dao.adiciona(this.matricula);			
		} else {
			dao.atualiza(this.matricula);
		}
		
		this.matricula = new Matricula();
		
		return "matricula";
	}

	public String cancelar() {
		this.matricula = new Matricula();
		return "matricula";
	}	
	
	public String cancelarNovo() {
		this.matricula = new Matricula();
		return "matricula";
	}

	public String cancelarSelecao() {
		this.novaMatricula = new Matricula();
		return "matricula";
	}

	public String editar() {
		dao.atualiza(this.novaMatricula);
		this.novaMatricula = new Matricula();
		return "matricula";
	}

	public List<Matricula> getMatriculas() {
		this.matriculas = dao.listaTodos();
		return matriculas;
	}

	public void setMatriculas(List<Matricula> matriculas) {
		this.matriculas = matriculas;
	}

	public Matricula getMatricula() {
		return this.matricula;
	}

	public void setMatricula(Matricula matricula) {
		this.matricula = matricula;
	}

	public Long getIdEstadoCivil() {
		return idEstadoCivil;
	}

	public void setIdEstadoCivil(Long idEstadoCivil) {
		this.idEstadoCivil = idEstadoCivil;
	}

	public Matricula getNovaMatricula() {
		return novaMatricula;
	}

	public void setNovaMatricula(Matricula matriculaSelecionada) {
		this.novaMatricula = matriculaSelecionada;
	}

}

7 Respostas

T

Tentei mudar minha estrategia. Estou tentando fazer tudo pelo proprio commandButton, mas mesmo assim, sem sucesso:

<p:commandButton id="novo" value="Novo" type="button"
									onclick="matriculaDialogo.show();"
									actionListener="#{matriculaBean.novo}"
									immediate="true" 
									ajax="false" >
									<f:ajax execute="@this" />
								</p:commandButton>

Alguem tem alguma ideia?

Obrigado

A

Indo por partes, para ativar o double click do data table tente utilizar o atributo: dblClickSelect=true.
Dê uma olhada no showcase do primefaces: http://www.primefaces.org/showcase/ui/datatableRowSelectionInstant.jsf

Inicialize o objeto no managedbean:

private Matricula matricula = new Matricula();

E no segundo caso, usando o commandButton, aqui vão algumas dicas:

E não há necessidade do f:ajax no p:commandButton,ele já é ajax por padrão, para o tipo type=“button”, se quiser o actionListener ocorra remova esse type.
Se entendi bem você precisa limpar os dados (botão novo), então não há necessidade do immediate, pesquise sobre objetivo do immediate. Prefira o oncomplete no lugar de onclick.

<p:commandButton id="novo" value="Novo"
        oncomplete="matriculaDialogo.show();"  
        update="localParaAtualizar"
        actionListener="#{matriculaBean.novo}"  > 
                           
</p:commandButton>

Remova o dialog de dentro do form e coloque um form dentro do dialog, pois ele não se comporta muito bem assim:
Algo do tipo:

</h:form> 
        <p:dialog id="formularioMatricula" header="Detalhes da Matrícula"  
                    widgetVar="matriculaDialogo" modal="true" dynamic="true" >  
               <h:form>          
                    <fieldset>  
  
                        <legend>Nova Matricula</legend>  
  
                            <h:panelGrid columns="2" >  
                              
                                <h:outputLabel value="Nome:" />  
                                <p:inputText value="#{matriculaBean.matricula.nome}" size="50" />  
      
                                <h:outputLabel value="Apelido:" />  
                                <p:inputText value="#{matriculaBean.matricula.apelido}" />  
      
                                <h:outputLabel value="Email:" />  
                                <p:inputText value="#{matriculaBean.matricula.email}" />  
      
                            </h:panelGrid>  
      
                            <h:panelGrid columns="4">  
      
                                <h:outputLabel value="Telefone 1:" />  
                                <p:inputMask mask="([telefone removido]"  
                                    value="#{matriculaBean.matricula.telefone1}" />  
      
                                <h:outputLabel value="Telefone 2:" />  
                                <p:inputMask mask="([telefone removido]"  
                                    value="#{matriculaBean.matricula.telefone2}" />  
      
                                <h:outputLabel value="Celular 1:" />  
                                <p:inputMask mask="([telefone removido]"  
                                    value="#{matriculaBean.matricula.celular1}" />  
      
                                <h:outputLabel value="Celular 2:" />  
                                <p:inputMask mask="([telefone removido]"  
                                    value="#{matriculaBean.matricula.celular2}" />  
      
                                <h:outputLabel value="C.P.F:" />  
                                <p:inputMask mask="[CPF removido]"  
                                    value="#{matriculaBean.matricula.cpf}" />  
      
                            </h:panelGrid>  
      
                            <h:panelGrid columns="5">  
      
                                <h:outputLabel value="Identidade:" />  
                                <p:inputText value="#{matriculaBean.matricula.identidade}" />  
      
                                <h:outputLabel value="Orgão Expeditor:" />  
                                <p:inputText value="#{matriculaBean.matricula.orgaoExpeditor}" />  
      
                            </h:panelGrid>  
      
                            <h:panelGrid columns="2">  
      
                                <h:outputLabel value="Data Expedição:" />  
                                <p:calendar value="#{matriculaBean.matricula.dataExpedicao}"  
                                    pattern="dd/MM/yyyy" />  
      
                                <h:outputLabel value="Estado Civil:" />  
                                <p:selectOneMenu value="#{matriculaBean.idEstadoCivil}">  
      
                                    <f:selectItems value="#{estadoCivilBean.estadosCivis}"  
                                        var="estadocivil" itemValue="#{estadocivil.id}"  
                                        itemLabel="#{estadocivil.descricao}" />  
      
                                </p:selectOneMenu>  
      
                                <h:outputLabel value="Nome da Mãe: " />  
                                <p:inputText value="#{matriculaBean.matricula.nomeMae}" size="50" />  
      
                                <h:outputLabel value="Nome do Pai: " />  
                                <p:inputText value="#{matriculaBean.matricula.nomePai}" size="50" />  
                                          
                                <p:commandButton value="Salvar"  
                                    action="#{matriculaBean.salvar}" ajax="false" />  
                                      
                                <p:commandButton value="Cancelar"  
                                    action="#{matriculaBean.cancelar}" ajax="false" />                                                     
                  
                            </h:panelGrid>                                  
  
                    </fieldset>  
               </h:form>          
           </p:dialog>
T

Olá pessoal. Ainda nao obtive sucesso com minha aplicaçao. Ora consigo acessar o metodo do meu bean porem o dialog nao renderiza e ora consigo renderizar o dialog e o metodo do bean não é executado.

Acho que o problema todo esta no meu commandButton, atualmente esta assim: Ele renderiza o dialog e não executa o metodo do bean.

<h:form id="novoForm">					
													
								<p:commandButton id="novo" value="Novo"
									type="button"
									onclick="matriculaDialogo.show();"
									actionListener="#{matriculaBean.novo}"
									ajax="false" >
									<f:ajax execute="@this" listener="#{matriculaBean.novo}" />
								</p:commandButton>
							
							</h:form>

Por favor, me deem uma luz!!
Se eu retirar o codigo ajax e tirar o ajax=“false” do commandbutton ele não renderiza o dialog, porém, executa o metodo do bean.

Obrigado

C

Boa Tarde,

Testar:

Se for utilizar actioListener seu método deve conter ActionEvent (import faces)

public void novo(ActionEvent event){ System.out.println("instanciando novo objeto matricula...."); this.matricula = new Matricula(); }
Se for utilizar action seu método deve retornar uma String

public String novo(){ System.out.println("instanciando novo objeto matricula...."); this.matricula = new Matricula(); return ""; }

Retire a sentença f:ajax do p:command e dependendo do negócio instancie a Matricula no seu Construtor.

T

CLEYSON:
Boa Tarde,

Testar:

Se for utilizar actioListener seu método deve conter ActionEvent (import faces)

public void novo(ActionEvent event){ System.out.println("instanciando novo objeto matricula...."); this.matricula = new Matricula(); }
Se for utilizar action seu método deve retornar uma String

public String novo(){ System.out.println("instanciando novo objeto matricula...."); this.matricula = new Matricula(); return ""; }

Retire a sentença f:ajax do p:command e dependendo do negócio instancie a Matricula no seu Construtor.

Bom dia.

Cleyson, executei as suas dicas mas mesmo assim não obtive sucesso.

O minha view esta da seguinte forma:

<!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:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.org/ui">

<ui:composition template="/_template.xhtml">

	<ui:define name="corpo">

		<h:form id="formulario">
			
			<h:messages styleClass="erros" />
			
			<h2>Matrículas</h2>

			<fieldset>
			
				<legend>Listagem</legend>
				
				<h:form id="matricula" >
					
					<p:remoteCommand id="novaMatricula" name="novaMatricula" action="#{matriculaBean.novo}" oncomplete="matriculaDialogo.show();" immediate="true" />
					
					<p:dataTable id="matriculas" var="matriculas"
						value="#{matriculaBean.matriculas}"
						emptyMessage="Nenhuma matrícula encontrada."
						selectionMode="single"
						selection="#{matriculaBean.matricula}"
						rowKey="#{matriculas.id}"
						dblClickSelect="true" >
												
						<p:ajax event="rowSelect" update=":formulario" 
							oncomplete="matriculaDialogo.show();" />
						
						<p:column id="nome" filterBy="#{matriculas.nome}"
							headerText="Nome">
							<h:outputText value="#{matriculas.nome}" />
						</p:column>
	
						<p:column id="apelido" filterBy="#{matriculas.apelido}"
							headerText="Apelido">
							<h:outputText value="#{matriculas.apelido}" />
						</p:column>
	
						<p:column id="cpf" filterBy="#{matriculas.cpf}" headerText="CPF">
							<h:outputText value="#{matriculas.cpf}" />
						</p:column>
						
						<f:facet name="footer">
																			
							<h:form id="novoForm">					
													
								<p:commandButton id="novo" value="Novo"
									oncomplete="matriculaDialogo.show();"
									actionListener="#{matriculaBean.novo}"
									ajax="false" >									
									<f:ajax execute="@this" />
								</p:commandButton>
							
							</h:form>
																																							
						</f:facet>						
		
					</p:dataTable>									
										
					<p:dialog id="formularioMatricula" header="Detalhes da Matrícula"
					widgetVar="matriculaDialogo" modal="true" dynamic="true" >
					
						<h:form>
										
							<fieldset>
		
								<legend>Nova Matricula</legend>
		
									<h:panelGrid columns="2" >
									
										<h:outputLabel value="Nome:" />
										<p:inputText value="#{matriculaBean.matricula.nome}" size="50" />
			
										<h:outputLabel value="Apelido:" />
										<p:inputText value="#{matriculaBean.matricula.apelido}" />
			
										<h:outputLabel value="Email:" />
										<p:inputText value="#{matriculaBean.matricula.email}" />
			
									</h:panelGrid>
			
									<h:panelGrid columns="4">
			
										<h:outputLabel value="Telefone 1:" />
										<p:inputMask mask="([telefone removido]"
											value="#{matriculaBean.matricula.telefone1}" />
			
										<h:outputLabel value="Telefone 2:" />
										<p:inputMask mask="([telefone removido]"
											value="#{matriculaBean.matricula.telefone2}" />
			
										<h:outputLabel value="Celular 1:" />
										<p:inputMask mask="([telefone removido]"
											value="#{matriculaBean.matricula.celular1}" />
			
										<h:outputLabel value="Celular 2:" />
										<p:inputMask mask="([telefone removido]"
											value="#{matriculaBean.matricula.celular2}" />
			
										<h:outputLabel value="C.P.F:" />
										<p:inputMask mask="[CPF removido]"
											value="#{matriculaBean.matricula.cpf}" />
			
									</h:panelGrid>
			
									<h:panelGrid columns="5">
			
										<h:outputLabel value="Identidade:" />
										<p:inputText value="#{matriculaBean.matricula.identidade}" />
			
										<h:outputLabel value="Orgão Expeditor:" />
										<p:inputText value="#{matriculaBean.matricula.orgaoExpeditor}" />
			
									</h:panelGrid>
			
									<h:panelGrid columns="2">
			
										<h:outputLabel value="Data Expedição:" />
										<p:calendar value="#{matriculaBean.matricula.dataExpedicao}"
											pattern="dd/MM/yyyy" />
			
										<h:outputLabel value="Estado Civil:" />
										<p:selectOneMenu value="#{matriculaBean.idEstadoCivil}">
			
											<f:selectItems value="#{estadoCivilBean.estadosCivis}"
												var="estadocivil" itemValue="#{estadocivil.id}"
												itemLabel="#{estadocivil.descricao}" />
			
										</p:selectOneMenu>
			
										<h:outputLabel value="Nome da Mãe: " />
										<p:inputText value="#{matriculaBean.matricula.nomeMae}" size="50" />
			
										<h:outputLabel value="Nome do Pai: " />
										<p:inputText value="#{matriculaBean.matricula.nomePai}" size="50" />
												
										<p:commandButton value="Salvar"
											action="#{matriculaBean.salvar}" ajax="false" />
											
										<p:commandButton value="Cancelar"
											action="#{matriculaBean.cancelar}" ajax="false" />													
						
									</h:panelGrid>								
		
							</fieldset>
					
						</h:form>
					
					</p:dialog>				
				
				</h:form>
			
			</fieldset>

		</h:form>

	</ui:define>

</ui:composition>

</html>

Da forma como esta eu consigo acessar o metodo no meu bean, porem, o dialog não renderiza.

Meu bean esta como coloquei no primeiro post, porem, o metodo novo() agora recebe ActionEvent.

Obrigado.

C

Favor testar:

Teste 1) O ayslanms já tinha dado a dica para você colocar o dialog fora do form principal

Teste 2) Faça um teste retirando os itens ui: composite e define, verifica se o problema persiste …

Teste 3) Faça um teste removendo os itens modal e dynamic do dialog e <f:ajax execute="@this" /> do commandButton

O problema também pode estar na lógica do Bean … talvez o seu objeto já tenha que estar criado (Construtor) … tive problemas com o picklist, eu abria o dialog com ele null e depois que clicava num botão colocava um array com minhas opções porém não atualizada o picklist, depois descobri que tinha que dar um setTarget para atualizar meu objeto …

T

Ola galera!
Depois de muita dor de cabeça consegui resolver meu problema. O que aconteceu foi uma serie de fatores, primeiro foram os benditos form aninhados que estava usando que estavam causando uma confusão no jsf. Coloquei um form abaixo do principal exclusivamente para o dialog. Alem disso, deixei meu commandButton da seguinte forma:

<p:commandButton id="novo" 
							value="Novo" 
							type="submit" 
							actionListener="#{matriculaBean.novo}" 
							oncomplete="matriculaDialogo.show();"
							update=":formCadastro" />

Engraçado que o type padrão deste componente é submit, mas, se eu tirar esse parametro, a coisa deixa de funcionar. Ainda foi conseguir compreender o pq deste comportamente, mas por hora, minha aplicação esta funcionando.
Obrigado a todos que ajudaram

Criado 28 de março de 2012
Ultima resposta 29 de mar. de 2012
Respostas 7
Participantes 3