I'm trying to put the currently iterated <p:dataTable var>
as a property of a managed bean using <f:setPropertyActionListener>
. However, it is always set as null
.
The view, dentistas.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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:composition template="/templates/template.xhtml">
<ui:define name="content">
<h:form id="formDentistas">
<p:growl autoUpdate="true" />
<p:commandButton icon="ui-icon-plus" value="Cadastrar"
id="cadastrar" oncomplete="dialogCadastrar.show()" />
<p:dataTable var="dentista" value="#{dentistaMB.dentistas}"
paginator="true" emptyMessage="Não foi encontrado nenhum registro"
rows="10" id="dataTableDentistas">
<f:facet name="header">Lista de Dentistas</f:facet>
<p:column headerText="Nome" sortBy="nome" filterBy="nome" id="nome"
width="200px">
#{dentista.pessoaFisica.nome}
</p:column>
<p:column headerText="Data Nascimento" sortBy="dataNascimento"
filterBy="dataNascimento" id="dataNascimento" width="60px">
#{dentista.pessoaFisica.dataNascimento}
</p:column>
<p:column headerText="CRO" sortBy="cro" filterBy="cro" id="cro"
width="60px">
#{dentista.cro}
</p:column>
<p:column headerText="Ações" style="width:50px;">
<p:commandButton value="Alterar" icon="ui-icon-pencil">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
<p:commandButton value="Remover" icon="ui-icon-trash"
actionListener="#{dentistaMB.deletar}">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
<ui:include src="/tabelas/dialog_insert_dentista.xhtml" />
</ui:define>
</ui:composition>
</h:body>
</html>
The managed bean, DentistaMBImpl
:
package br.com.odontonew.mb;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.convert.FacesConverter;
import javax.faces.event.ActionEvent;
import org.apache.log4j.Logger;
import org.primefaces.context.RequestContext;
import br.com.odontonew.bean.Dentista;
import br.com.odontonew.bean.EstadoCivil;
import br.com.odontonew.bean.PessoaFisica;
import br.com.odontonew.bean.Sexo;
import br.com.odontonew.bean.SituacaoPessoa;
import br.com.odontonew.bean.Uf;
import br.com.odontonew.bo.BasicBO;
import br.com.odontonew.exception.BOException;
@ManagedBean(name = "dentistaMB")
@ViewScoped
public class DentistaMBImpl extends BasicMBImpl {
private Logger logger = Logger.getLogger(DentistaMBImpl.class);
@ManagedProperty("#{dentistaBO}")
private BasicBO dentistaBO;
private Dentista dentista;
private Dentista selectedDentista;
private List<Dentista> dentistas;
// Lists
private List<EstadoCivil> estadosCivis;
private List<SituacaoPessoa> situacoesPessoa;
private List<Sexo> sexos;
private List<Uf> ufs;
@PostConstruct
public void init() {
dentista = new Dentista();
dentista.setPessoaFisica(new PessoaFisica());
dentista.getPessoaFisica().setSexo(new Sexo());
dentista.getPessoaFisica().setEstadoCivil(new EstadoCivil());
dentista.getPessoaFisica().setSituacao(new SituacaoPessoa());
dentista.getPessoaFisica().setUf(new Uf());
estadosCivis = (List<EstadoCivil>) dentistaBO
.findByNamedQuery(EstadoCivil.FIND_ALL);
situacoesPessoa = (List<SituacaoPessoa>) dentistaBO
.findByNamedQuery(SituacaoPessoa.FIND_ALL);
sexos = (List<Sexo>) dentistaBO.findByNamedQuery(Sexo.FIND_ALL);
ufs = (List<Uf>) dentistaBO.findByNamedQuery(Uf.FIND_ALL);
}
public void salvar(ActionEvent event) {
try {
dentista = (Dentista) dentistaBO.save(dentista);
addInfoMessage("Dentista salvo com sucesso");
RequestContext.getCurrentInstance().execute(
"dialogCadastrar.hide()");
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
public void atualizar(ActionEvent event) {
try {
dentistaBO.update(selectedDentista);
addInfoMessage("Dentista atualizado com sucesso");
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
public void deletar(ActionEvent event) {
try {
dentistaBO.delete(selectedDentista);
addInfoMessage("Dentista deletado com sucesso");
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
public List<Dentista> getDentistas() {
try {
if (dentistas == null)
dentistas = (List<Dentista>) dentistaBO
.findByNamedQuery(Dentista.FIND_ALL_COMPLETO);
return dentistas;
} catch (BOException e) {
addErrorMessage(e.getMessage());
return null;
}
}
/* gets and sets */
public Dentista getSelectedDentista() {
return selectedDentista;
}
public void setSelectedDentista(Dentista selectedDentista) {
this.selectedDentista = selectedDentista;
}
public Dentista getDentista() {
return dentista;
}
public void setDentista(Dentista dentista) {
this.dentista = dentista;
}
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
public List<EstadoCivil> getEstadosCivis() {
return estadosCivis;
}
public void setEstadosCivis(List<EstadoCivil> estadosCivis) {
this.estadosCivis = estadosCivis;
}
public List<SituacaoPessoa> getSituacoesPessoa() {
return situacoesPessoa;
}
public void setSituacoesPessoa(List<SituacaoPessoa> situacoesPessoa) {
this.situacoesPessoa = situacoesPessoa;
}
public List<Sexo> getSexos() {
return sexos;
}
public void setSexos(List<Sexo> sexos) {
this.sexos = sexos;
}
public void setDentistas(List<Dentista> dentistas) {
this.dentistas = dentistas;
}
public List<Uf> getUfs() {
return ufs;
}
public void setUfs(List<Uf> ufs) {
this.ufs = ufs;
}
public BasicBO getDentistaBO() {
return dentistaBO;
}
public void setDentistaBO(BasicBO dentistaBO) {
this.dentistaBO = dentistaBO;
}
}
Here,
<p:commandButton value="Remover" icon="ui-icon-trash"
actionListener="#{dentistaMB.deletar}">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
you're performing the delete in an actionListener
method instead of an action
method. This is not right. Business actions should be performed in the action
method. All action listeners, including the <f:setPropertyActionListener>
, are invoked before action
method in the very same order as they are declared and assigned on the command component. So, in effects, the delete is first invoked and then the property is set. That explains why the property is null
during the delete.
The fix is simple: make it a real action
method:
<p:commandButton value="Remover" icon="ui-icon-trash"
action="#{dentistaMB.deletar}">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
Don't forget to remove the ActionEvent
argument:
public void deletar() {
// ...
}
Unrelated to the concrete problem, if you happen to target a Servlet 3.0 / EL 2.2 compatible container, then you can even get rid of that <f:setPropertyActionListener>
altogether:
<p:commandButton value="Remover" icon="ui-icon-trash"
action="#{dentistaMB.deletar(dentista)}" />
With:
public void deletar(Dentista selectedDentista) {
// ...
}
See also point 3 of How can I pass selected row to commandLink inside dataTable?