Problema com auto complete primefaces

20 respostas
S

Olá pessoal, estou tendo um problema com um autocomplete do Primefaces, que simplesmente traz o objeto inteiro e não apenas um atributo.
Quero que traga apenas o nome da empresa, e está trazendo tudo.

Podem me ajudar?

Código da consulta:

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

Managed Bean:

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;
	}

Página:

<p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"
						completeMethod="#{empresaBean.autocompleteEmpresa}"
						itemLabel="#{empresa.nome}" itemValue="#{empresa}"
						converter="Converter"
						onkeyup="this.value = this.value.toUpperCase();">
					</p:autoComplete>

20 Respostas

R

Nunca fiz isso mas fica uma sugestão:

Não tem como fazer essa lista ser de String, e adicionar somente os nomes? ou você precisa do objeto todo?
Se for o caso, não resolveria sobreescrever o toString() para retornar o nome ?

S

Pode dar uma dica de como fazer isso?

R

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

S

A hql mudaria?

R

Ah, você pode implementar um converter, e fazer da maneira que ja estava fazendo. Muito mais fácil.

http://www.primefaces.org/showcase/ui/autoCompletePojo.jsf

S

Digao, não sou experiente em jsf, o que de fato faz um converter?
e como implementar, nesse caso?

S

Desse modo como voce me disse anteriormente dá problema no getNome.

R
smnj:
Digao, não sou experiente em jsf, o que de fato faz um converter? e como implementar, nesse caso?
Bom, um converter é o que vai converter (obviamente) um objeto do seu modelo, para uma String que você queira apresentar na sua View. Ficou confuso? Usando o próprio exemplo do PrimeFaces
public class PlayerConverter implements Converter {  
  
    public static List&lt;Player&gt; playerDB;  
  
    static {  
        playerDB = new ArrayList&lt;Player&gt;();  
  
        playerDB.add(new Player("Messi", 10));  
        playerDB.add(new Player("Bojan", 9));  
        playerDB.add(new Player("Henry", 14));  
        playerDB.add(new Player("Iniesta", 8));  
        playerDB.add(new Player("Villa", 7));  
        playerDB.add(new Player("Xavi", 6));  
        playerDB.add(new Player("Puyol", 5));  
        playerDB.add(new Player("Afellay", 20));  
        playerDB.add(new Player("Abidal", 22));  
        playerDB.add(new Player("Alves", 2));  
        playerDB.add(new Player("Pique", 3));  
        playerDB.add(new Player("Keita", 15));  
        playerDB.add(new Player("Busquets", 16));  
        playerDB.add(new Player("Adriano", 21));  
        playerDB.add(new Player("Valdes", 1));  
        playerDB.add(new Player("Thiago", 30));  
    }  
  
    public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {  
        if (submittedValue.trim().equals("")) {  
            return null;  
        } else {  
            try {  
                int number = Integer.parseInt(submittedValue);  
  
                for (Player p : playerDB) {  
                    if (p.getNumber() == number) {  
                        return p;  
                    }  
                }  
  
            } catch(NumberFormatException exception) {  
                throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid player"));  
            }  
        }  
  
        return null;  
    }  
  
    public String getAsString(FacesContext facesContext, UIComponent component, Object value) {  
        if (value == null || value.equals("")) {  
            return "";  
        } else {  
            return String.valueOf(((Player) value).getNumber());  
        }  
    }  
}

No método getAsString, você recebe o objeto em si, no seu caso a Empresa, e retorna dela, uma representação textual (String) que a identifique da maneira que você quer, no caso, seria o nome.

No método getAsObject, você recebe a representação textual gerada anteriormente, e precisa a partir dela, obter o objeto para atualizar o seu modelo (ManagedBean), que no caso, ele itera a lista procurando pelo nome, quando encontra o objeto correto o retorna.

Deu pra entender?

S

Não é difícil entender, agora, implementar, é outra história…

R

Mas aí a gente te ajudar :slight_smile: Comece um conversor aí, implemente primeiro o getAsString porque é bem mais fácil,
depois tente o getAsObject, qualquer dúvida posta aqui.

S

Beleza então.

S

creio que isso não seria sufuciente:

package com.portal.view;

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

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

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

	public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {

		if (arg2.trim().equals(""))
			return null;

		EmpresaRN empresaRN = new EmpresaRN();

		System.out.println("passando no converter getAsObject ");

		if (empresaRN != null) {
			System.out
					.println("passando no converter getAsObject dentro do método");
			return empresaRN;
		}

		return null;
	}

	@Override
	public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
		System.out.println("passando no converter getAsString");
		if (arg2 != null && arg2 != "") {
			System.out
					.println("passando no converter getAsString dentro do método");
			Empresa e = (empresa) arg2;
			return b.getNome();

		}

		return "";
	}
}
R

bom, o getAsString está correto até, mas ficaria muito mais legível se ficasse igual ao do exemplo do PrimeFaces, só que ao invés de fazer o cast para Player, você faz para Empresa, e ao invés de invocar o getNumber você invoca o getNome.

Quanto ao getAsObject, ele não está correto, você precisaria de uma lista, pra retornar o objeto que você ja tem, se o seu converter for usado somente nessa tela, você pode buscar a lista diretamente do managed bean, fazendo algo como ELContext elContext = arg0.getELContext(); List<Empresa> list = ((MeuMB) elContext.getELResolver().getValue(elContext, null, "meuMB")).getListEmpresas(); Ja vi casos onde buscam diretamente do banco a lista, tornando o conversor mais genérico, e também garantindo que os dados são atuais. não sei o que é melhor para o seu caso.

S

Cara, vê se é isso:

package com.portal.view;

import java.util.ArrayList;
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 com.portal.empresa.Empresa;

public class EntityConverter implements Converter {

	public static List&lt;Empresa&gt; empresas;

	static {
		empresas = new ArrayList&lt;Empresa&gt;();
	}

	public Object getAsObject(FacesContext facesContext, UIComponent component,
			String submittedValue) {
		if (submittedValue.trim().equals("")) {
			return null;
		} else {
			try {
				String nome = submittedValue;

				for (Empresa e : empresas) {
					if (e.getNome() == nome) {
						return e;
					}
				}

			} catch (NumberFormatException exception) {
				throw new ConverterException(new FacesMessage(
						FacesMessage.SEVERITY_ERROR, "Conversion Error",
						"Not a valid value"));
			}
		}

		return null;
	}

	public String getAsString(FacesContext facesContext, UIComponent component,
			Object value) {
		if (value == null || value.equals("")) {
			return "";
		} else {
			return String.valueOf(((Empresa) value).getNome());
		}
	}
}
C

o problemas esta nesse codigo seu :

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

o certo para o que voce quer fazer é:

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa.nome}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

a propriedade itemValue é o valor que ira para o value do componente, conseguentemente para o seu managedbean, como voce que so o nome no item value voce tem quer por o object.property dele, fazendo isso ira funcionar

C

o problemas esta nesse codigo seu :

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

o certo para o que voce quer fazer é:

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa.nome}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

a propriedade itemValue é o valor que ira para o value do componente, conseguentemente para o seu managedbean, como voce que so o nome no item value voce tem quer por o object.property dele, fazendo isso ira funcionar

C

o problemas esta nesse codigo seu :

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

o certo para o que voce quer fazer é:

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa.nome}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

a propriedade itemValue é o valor que ira para o value do componente, conseguentemente para o seu managedbean, como voce que so o nome no item value voce tem quer por o object.property dele, fazendo isso ira funcionar

C

o problemas esta nesse codigo seu :

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

o certo para o que voce quer fazer é:

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa"  
    completeMethod="#{empresaBean.autocompleteEmpresa}"  
    itemLabel="#{empresa.nome}" itemValue="#{empresa.nome}"  
    converter="Converter"  
    onkeyup="this.value = this.value.toUpperCase();"&gt;  
&lt;/p:autoComplete&gt;

a propriedade itemValue é o valor que ira para o value do componente, conseguentemente para o seu managedbean, como voce que so o nome no item value voce tem quer por o object.property dele, fazendo isso ira funcionar

S

Va LE U MANOLO Acabaram com todos os meus problemas.!@!!!

S

E aí, Digão, tudo bem, um colega ajudou , o problema era na visão, faltava um atributo. Funcionou, agora, o problema é outro:

Este botão parou de funcionar, já que a intenção era que buscasse o valor do campo <p:autocomplete>
autocomplete:

&lt;p:autoComplete value="#{empresaBean.empresa.nome}" var="empresa" completeMethod="#{empresaBean.autocompleteEmpresa}" itemLabel="#{empresa.nome}" itemValue="#{empresa.nome}" converter="Converter" onkeyup="this.value = this.value.toUpperCase();" size="20" style="font-size:12px;"&gt; &lt;/p:autoComplete&gt;

botão abaixo:

&lt;div id="botaopesq"&gt; &lt;p:commandLink actionListener="#{empresaBean.buscarPorNome()}" title="Pesquisar" value="#{empresa.nome}" action="pesquisa"&gt; &lt;h:graphicImage library="images" name="botao.png" width="118" height="27" style="border:0" /&gt; &lt;f:setPropertyActionListener target="#{empresaBean.empresa}" value="#{empresa}" /&gt; &lt;/p:commandLink&gt;

Criado 13 de junho de 2012
Ultima resposta 14 de jun. de 2012
Respostas 20
Participantes 3