Problema em obter valor selecionado em autocomplete primefaces

Olá pessoal, estou tendo um probleminha chato aqui, já postei vários foruns, mas não consigo obter sucesso.
Bem, a idéia é que quando puder clicar sobre um valor sugerido em um autocomplete, possa obtê-lo e setar uma variável.
Esta será necessária para construir uma lista. O problema é que não consigo obter o valor ao clicar sobre ele.
Obrigado, desde já.

Página:


<div id="campos">
					<p:autoComplete id="complete" value="#{empresaBean.empresa.nome}"
						var="empresa" completeMethod="#{empresaBean.autocompleteEmpresa}"
						itemLabel="#{empresa.nome}" itemValue="#{empresa.nome}"
						converter="Converter"
						onkeyup="this.value = this.value.toUpperCase();" maxResults="5"
						size="82">
					<p:ajax event="itemSelect" update="complete" />
					</p:autoComplete>
				</div>
				<div id="botaopesq">
					<p:commandLink actionListener="#{empresaBean.buscarPorNome}"
						title="Pesquisar" value="#{empresa.nome}" action="pesquisa">
						<h:graphicImage library="images" name="botao.png" width="118"
							height="27" style="border:0" />
						<f:setPropertyActionListener target="#{empresaBean.empresa}"
							value="#{empresa}" />
					</p:commandLink>

Método usado para autocompletar:


public List<Empresa> autocompleteEmpresa(String query) {
		List<Empresa> results = new ArrayList<Empresa>();
		if (empresas.isEmpty()) {
			this.empresas = empresaRN.complete();
		}
		for (Empresa e : empresas) {
			if (e.getNome().startsWith(query)) {
				results.add(e);
			}
		}
		return results;
	}

Converter usado:

package com.portal.view;

import java.lang.reflect.Field;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.persistence.Id;

@FacesConverter(value = "Converter")
public class EntityConverter implements Converter {

	public Object getAsObject(FacesContext ctx, UIComponent component,
			String value) {
		System.out.println("ECV-GO");
		return value;
	}

	public String getAsString(FacesContext ctx, UIComponent component,
			Object obj) {
		System.out.println("ECV-GS");
		if (obj != null && !"".equals(obj)) {
			String id;
			try {
				id = this.getId(getClazz(ctx, component), obj);
				if (id == null) {
					id = "";
				}
				id = id.trim();
				component.getAttributes().put(id,
						getClazz(ctx, component).cast(obj));
				return id;
			} catch (SecurityException e) {
				e.printStackTrace(); // seu log aqui
			} catch (IllegalArgumentException e) {
				e.printStackTrace(); // seu log aqui
			} catch (NoSuchFieldException e) {
				e.printStackTrace(); // seu log aqui
			} catch (IllegalAccessException e) {
				e.printStackTrace(); // seu log aqui
			}
		}
		return null;
	}

	private Class<?> getClazz(FacesContext facesContext, UIComponent component) {
		return component.getValueExpression("value").getType(
				facesContext.getELContext());
	}

	public String getId(Class<?> clazz, Object obj) throws SecurityException,
			NoSuchFieldException, IllegalArgumentException,
			IllegalAccessException {
		for (Field field : clazz.getDeclaredFields()) {
			if ((field.getAnnotation(Id.class)) != null) {
				Field privateField = clazz.getDeclaredField(field.getName());
				privateField.setAccessible(true);
				if (privateField.get(clazz.cast(obj)) != null) {
					return (String) field.getType()
							.cast(privateField.get(clazz.cast(obj))).toString();
				} else {
					return null;
				}
			}
		}
		return null;
	}
}

Método no DAO usado para o autocomplete:

	@SuppressWarnings("unchecked")
	public List<Empresa> complete() {
		Query query = this.session.createQuery("Select e From Empresa as e");
		return query.list();

	}

Aqui tem um exemplo com autocomplete funcionando e com código fonte para download: Aplicação Web Completa Tomcat JSF Primefaces JPA Hibernate

Muito obrigado, meu caro, vou testar ver o que tem de errado através do teu exemplo aqui, foi de grande ajuda até aqui.
Se não conseguir, postarei as dúvidas.

Olá, JakeFrog, tudo bem?
olhei o exemplo, tentei mudar o converter, porém não tive sucesso, pode me ajudar?

Não sei se é assim, mas este método deveria obter o objeto pelo id:

	public Empresa carregar(Integer id) {
		return this.empresaDAO.carregar(id);
	}

Converter

[code]
package com.portal.view;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;

import com.portal.empresa.Empresa;
import com.portal.empresa.EmpresaRN;

@FacesConverter(value = "Converter")
public class EntityConverter implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component,
		String value) {
	if (value != null && value.trim().length() > 0) {
		Integer id = Integer.valueOf(value);
		try {
			EmpresaRN empresaRN = new EmpresaRN();
			return empresaRN.carregar(id);
		} catch (Exception e) {
			throw new ConverterException(
					"Não foi possível encontrar a a empresa de código"
							+ value + "." + e.getMessage());
		}
	}
	return null;
}

@Override
public String getAsString(FacesContext context, UIComponent component,
		Object value) {
	if (value != null) {
		Empresa empresa = (Empresa) value;
		return String.valueOf(empresa.getId());
	}
	return "";

}

}[/code]

E qual o erro que você teve?

O autocomplete parou de funcionar.

Será que estou errando o converter?

Cara, debuga aí. Está chamando o método do complete? Se não, tem coisa errada aí.

é, parece bug no converter.

Como resolver?

27/06/2012 15:51:43 com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback visit
GRAVE: java.lang.ClassCastException: com.portal.empresa.Empresa cannot be cast to java.lang.String

Seu p:converter está errado. olha a mensagem de erro, ele está falando que está passando uma string.

Confira no exemplo como está o itemValue e compare com o seu.

teve outro problema agora.

Bem, eu obtenho o que seleciono, porém, se eu digitar outro valor e clicar fora, o valor do campo some.

		<p:autoComplete id="complete" value="#{empresaBean.empresa}"
						var="empresa" completeMethod="#{empresaBean.autocompleteEmpresa}"
						itemLabel="#{empresa.nome}" itemValue="#{empresa}"
						onkeyup="this.value = this.value.toUpperCase();" maxResults="5"
						size="82">
					<p:ajax event="itemSelect" update="complete" />
					</p:autoComplete>

Consegui obter o valor selecionado através do ID, no converter, porém isso eu gostaria de fazer no autoComplete, era realmente o que eu queria.
Mas passei a ter um segundo problema.
quero que, quando eu digite qualquer coisa no input, e submeta também possa através do que eu passar, submeter uma lista,que era o que anteriormente funcionava.
Terei que mudar o converter para que isso possa acontecer?
Me ajuda, por favor.

Olá JakeFrog, está ocupado agora?
Pode me ajudar com um probleminha?

Olá pessoal.

Sei que o post já foi aberto há um tempo, mas estou com um problema parecido.
Indiquei na propriedade selectListener do p:autocomplete o método que ele deveria acessar toda vez que um objeto das sugestões apresentadas fosse selecionado. No entanto, nada acontece quando seleciono uma pessoa, por exemplo.

Vocês podem me ajudar?

NOTA: PrimeFaces 2.2.1, JSF 2.0, JEE 6

página .xhtml

<p:autoComplete id="pessoaBusca" value="#{pacienteMB.pessoaSelecionada}" completeMethod="#{pacienteMB.completePessoa}" var="pessoa" itemLabel="#{pessoa.nomePess}" itemValue="#{pessoa}" converter="pessoaConverter" selectListener="#{pacienteMB.handleSelect}" onSelectUpdate="messages"/>

Managed Bean

[code]//método utilizado pelo componente p:autocomplete para buscar as Pessoas já cadastradas no DB
public List completePessoa(String query) {
List sugestoes = new ArrayList();
List pessoas = new TrataPaciente().alimentaAutoComplete();
for(Pessoa p : pessoas) {
if(p.getNomePess().startsWith(query))
sugestoes.add§;
}
return sugestoes;
}

public void handleSelect(SelectEvent event) {
    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected:" + event.getObject().toString(), null);
    FacesContext.getCurrentInstance().addMessage(null, message);
}[/code]

Alan, prefiro utilizar o autocomplete do Richfaces, mas, gosto do aspecto visual do prime, bem, de antemão, não parece que seus métodos estão errados, mas preciso também ver seu converter.
Poste-o por favor.
Outra coisa: o value do p:autocomplete tem de ter com value o teu objeto, por isso, gostaria que postasse todo o teu mBean.
pela tarde, amanhã(dia 1) vejo com calma teu código, mas de antemão, exceto o converter que ainda não vi, parece correto.

Valeu pela atenção smnj!
Como solicitado, segue abaixo os códigos:

Converter

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */

package controle;

import dominio.TrataPaciente;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;
import persistencia.Pessoa;

/**
*

  • @author Alan Ribeiro
    */

@FacesConverter(value=“pessoaConverter”)
public class PessoaConverter implements Converter{

List<Pessoa> pessoas = new TrataPaciente().alimentaAutoComplete();

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
    if (value.trim().equals("")) {
        return null;
    }else{
        try{
            int number = Integer.parseInt(value);
            for(Pessoa p : pessoas) {
                if (p.getIdPess() == number) {
                    return p;
                }
            }
        } catch(NumberFormatException e) {
            System.out.println(e);
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro de Conversão", "Esta [Pessoa] não é válida."));
        }
    }
    return null;
    //throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    if (value == null || value.equals("")) {
        return "";
    }else{
        return String.valueOf(((Pessoa) value).getIdPess());
    }
    //throw new UnsupportedOperationException("Not supported yet.");
}

}
[/code]
MBean

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package controle;

import dominio.TrataPaciente;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import org.primefaces.event.SelectEvent;
import persistencia.Paciente;
import persistencia.Pessoa;

/**
*

  • @author Alan Ribeiro
    */
    public class PacienteMB {

    private Pessoa pessoa = null;
    private Paciente paciente = null;
    private Pessoa pessoaSelecionada = null;

    private String nomeBusca = null;
    private String maeBusca = null;
    private Date dtnascBusca = null;
    private String chamaMetodo = null;

    private boolean disabledPesquisa = false;
    private boolean disabledNovo = true;
    private boolean disabledSalvar = true;
    private boolean disabledEditar = true;
    private boolean disabledCancelar = true;
    private boolean disabledCampos = true;

    public PacienteMB() {
    }

    public String salvaPaciente() {
    FacesContext ctx = FacesContext.getCurrentInstance();
    ctx.getExternalContext().getFlash().setKeepMessages(true);
    TrataPaciente tp = new TrataPaciente();

     if (getPaciente().getEstadoPac() == null)
         getPaciente().setEstadoPac("ATIVO");
    
     String retorno = tp.cadPaciente(getPessoa(), getPaciente());
     if (retorno.equals("erro")) {
         ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "ATENÇÃO: ", "ATENÇÃO:  Não foi possível finalizar o cadastro deste Paciente. Causa: " + tp.getMsgException()));
     } else if (retorno.equals("ok")) {
         ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "INFORMAÇÃO:", "Paciente [" + getPessoa().getNomePess() + "] cadastrado com sucesso!"));
     } else if (retorno.equals("cadExistente")) {
         ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "ATENÇÃO: ", "ATENÇÃO:  Já existe um registro para esta pessoa."));
     } else {
         return retorno;
     }
     return null;
    

    }

    public String editarPaciente() {
    FacesContext ctx = FacesContext.getCurrentInstance();
    ctx.getExternalContext().getFlash().setKeepMessages(true);
    TrataPaciente tp = new TrataPaciente();

     if (getPaciente().getEstadoPac() == null)
         getPaciente().setEstadoPac("ATIVO");
    
     String retorno = tp.editPaciente(getPessoa(), getPaciente());
     if (retorno.equals("ok")) {
         ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "INFORMAÇÃO: ", "As informações foram atualizadas com sucesso!"));
     } else if (retorno.equals("erro")) {
         ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "ATENÇÃO: ", "ATENÇÃO:  As informações não foram atualizadas. Causa: " + tp.getMsgException()));
     } else {
         return retorno;
     }
     return null;
    

    }

    //método utilizado pelo componente p:autocomplete para buscar as Pessoas já cadastradas no DB
    public List completePessoa(String query) {
    List sugestoes = new ArrayList();
    List pessoas = new TrataPaciente().alimentaAutoComplete();
    for(Pessoa p : pessoas) {
    if(p.getNomePess().startsWith(query))
    sugestoes.add§;
    }
    return sugestoes;
    }

    public void handleSelect(SelectEvent event) {
    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, “Selected:” + event.getObject().toString(), null);
    FacesContext.getCurrentInstance().addMessage(null, message);
    }

    public String pesquisaCadastro() {
    try{
    FacesContext ctx = FacesContext.getCurrentInstance();
    ctx.getExternalContext().getFlash().setKeepMessages(true);
    //setPessoa(null);
    //setPaciente(null);
    TrataPaciente tp = new TrataPaciente();

     //Pessoa pess = tp.buscaPessoaCadastro(getNomeBusca(), getMaeBusca(), getDtnascBusca());
     Pessoa pess = tp.buscaPessoaCadastro(getPessoaSelecionada().getNomePess(), getPessoaSelecionada().getMaePess(), getPessoaSelecionada().getDtnascPess());
     if (pess != null) {
         disabledBotoesPesqEdit();
         setChamaMetodo("editar");
         Paciente pac = tp.buscaPacienteCadastro(pess.getIdPess());
         if (pac != null) {
             ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "INFO: ", "Paciente encontrado: " + pess.getNomePess()));
             setPessoa(pess);
             setPaciente(pac);
         } else {
             ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "INFO: ", "Paciente não encontrado, mas já existe informações desta Pessoa no Sistema. Favor completar o cadastro."));
             setPessoa(pess);
             setPaciente(null);
         }
     } else {
         disabledBotoesPesqNovo();
         setChamaMetodo("salvar");
         ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "ATENÇÃO: ", "ATENÇÃO: Paciente não encontrado. "));
     }
     }catch (Exception e){
         System.out.println(e);
     }
     return null;
    

    }

    /* ***********************************************

    • Métodos de habilida/desabilita botões e campos
    • ***********************************************/
      public void actionCommandButtonNovo(){
      Pessoa p = new Pessoa();
      p.setNomePess(nomeBusca);
      p.setMaePess(maeBusca);
      p.setDtnascPess(dtnascBusca);
      setPessoa§;
      disabledBotoesSalvaCancel();
      }

    public void actionCommandButtonSalvar(){
    if(getChamaMetodo().equals(“salvar”)){
    salvaPaciente();
    }else if(getChamaMetodo().equals(“editar”)){
    editarPaciente();
    }
    disabledBotoesGenerico();
    }

    public void actionCommandButtonEditar(){
    disabledBotoesSalvaCancel();
    }

    public void actionCommandButtonCancelar(){
    disabledBotoesPesqEdit();
    }

    public void disabledBotoesPesqNovo() {
    setDisabledPesquisa(false);
    setDisabledNovo(false);
    setDisabledSalvar(true);
    setDisabledEditar(true);
    setDisabledCancelar(true);
    setDisabledCampos(true);
    }

    public void disabledBotoesPesqEdit() {
    setDisabledPesquisa(false);
    setDisabledNovo(true);
    setDisabledSalvar(true);
    setDisabledEditar(false);
    setDisabledCancelar(true);
    setDisabledCampos(true);
    }

    public void disabledBotoesSalvaCancel() {
    setDisabledPesquisa(true);
    setDisabledNovo(true);
    setDisabledSalvar(false);
    setDisabledEditar(true);
    setDisabledCancelar(false);
    setDisabledCampos(false);
    }

    public void disabledBotoesGenerico() {
    setDisabledPesquisa(false);
    setDisabledNovo(true);
    setDisabledSalvar(true);
    setDisabledEditar(true);
    setDisabledCancelar(true);
    setDisabledCampos(true);
    }

    /* *****************************

    • Métodos gets e sets
    • *****************************/
      public Paciente getPaciente() {
      if (paciente == null) {
      paciente = new Paciente();
      }
      return paciente;
      }

    public void setPaciente(Paciente paciente) {
    this.paciente = paciente;
    }

    public Pessoa getPessoa() {
    if (pessoa == null) {
    pessoa = new Pessoa();
    }
    return pessoa;
    }

    public void setPessoa(Pessoa pessoa) {
    this.pessoa = pessoa;
    }

    public Pessoa getPessoaSelecionada() {
    return pessoaSelecionada;
    }

    public void setPessoaSelecionada(Pessoa pessoaSelecionada) {
    this.pessoaSelecionada = pessoaSelecionada;
    }

    public Date getDtnascBusca() {
    return dtnascBusca;
    }

    public void setDtnascBusca(Date dtnascBusca) {
    this.dtnascBusca = dtnascBusca;
    }

    public String getMaeBusca() {
    return maeBusca;
    }

    public void setMaeBusca(String maeBusca) {
    this.maeBusca = maeBusca;
    }

    public String getNomeBusca() {
    return nomeBusca;
    }

    public void setNomeBusca(String nomeBusca) {
    this.nomeBusca = nomeBusca;
    }

    public boolean isDisabledCancelar() {
    return disabledCancelar;
    }

    public void setDisabledCancelar(boolean disabledCancelar) {
    this.disabledCancelar = disabledCancelar;
    }

    public boolean isDisabledEditar() {
    return disabledEditar;
    }

    public void setDisabledEditar(boolean disabledEditar) {
    this.disabledEditar = disabledEditar;
    }

    public boolean isDisabledNovo() {
    return disabledNovo;
    }

    public void setDisabledNovo(boolean disabledNovo) {
    this.disabledNovo = disabledNovo;
    }

    public boolean isDisabledPesquisa() {
    return disabledPesquisa;
    }

    public void setDisabledPesquisa(boolean disabledPesquisa) {
    this.disabledPesquisa = disabledPesquisa;
    }

    public boolean isDisabledSalvar() {
    return disabledSalvar;
    }

    public void setDisabledSalvar(boolean disabledSalvar) {
    this.disabledSalvar = disabledSalvar;
    }

    public boolean isDisabledCampos() {
    return disabledCampos;
    }

    public void setDisabledCampos(boolean disabledCampos) {
    this.disabledCampos = disabledCampos;
    }

    public String getChamaMetodo() {
    return chamaMetodo;
    }

    public void setChamaMetodo(String chamaMetodo) {
    this.chamaMetodo = chamaMetodo;
    }

}
[/code]

smnj, não sei se é pertinente, mas tem um detalhe que não mencionei: o p:autocomplete está em dentro de um p:dialog.
Vlw!

Olá, Alan.
Tudo bem?
Alan, me diz uma coisa:
O que você espera é um tipo de filtro dinâmico, é isso?

Olá smnj!
O que preciso é o seguinte:

Antes do usuário efetuar o cadastro de um paciente, o sistema solicita uma pesquisa no DB para verificar se o paciente a ser cadastrado já existe. Sendo assim, a primeira coisa a se fazer quando acesso a página cadPaciente.xhtml é clicar em “Pesquisar”. Este botão dispara um p:dialog que contem nome, mãe e data de nascimento do paciente a ser pesquisado.

Estou colocando o p:autocomplete no campo “nome” e preciso que, ao selecionar uma das sugestões apresentadas, o método “handleSelect” seja acessado e sete os campos mae e datanasc., impedidno que o usuário tente fazer uma pesquisa com dados que não estão registrados no DB.

Sei que este método ("handleSelect) não tem código para que faça os sets, porém, em testes anteriores havia código sim, e percebi (pela depuração) que o método sequer é acessado.

Bom, não sei se fui claro, mas é isso. Qualquer coisa pergunte novamente.

Agradecido pela atenção.
Alan.