Problema com Converter de Objeto em selectOneMenu

8 respostas
javer
Tenho esse selectOneMenu que lista uma relação de Tarifas de Cálculo de Frete, preciso que quando selecione um item atualize os campos do formulário (por enquanto apenas um campo: nome) mas não está funcionando, parece que o valueChangeListener nunca é disparado no BB . Como sou novo "nisso" acho que estou fazendo alguma coisa errada. [img]http://lh5.ggpht.com/_iPEXgELGyFA/SieYZ8JC4DI/AAAAAAAAAzM/v77EJeCUeiU/Tarifa.Calculo.Frete.Francisco.gif[/img] Lembrando que uso: RichFaces + Facelets + JSF xhtml:
<h:form id="formTarifasCadastradas">
    <!-- Lista das Tarifas Cadastradas -->
    <h:outputLabel for="tarifas" value="Tarifas cadastradas:"/>
    <h:selectOneMenu
        id="tarifas"
        value="#{tarifaBean.item}"
        style="width:150px"
        valueChangeListener="#{tarifaBean.tarifaChanged}"
        reRender="nome" immediate="true" >
        <f:selectItems var="tarifa" id="tarifa" value="#{tarifaBean.listaTarifas}" />
    </h:selectOneMenu>
</h:form>
<br/>
<br/>

<a4j:region>
    <rich:tabPanel switchType="ajax">
        <rich:tab label="Dados Principais">
            <a4j:form requestDelay="20" ignoreDupResponses="true" id="formDados">
                <h:panelGrid width="100%" columns="3" border="0">
                    <h:outputLabel for="nome" value="Nome da Tarifa"/>
                    <h:inputText id="nome" size="50" value="#{tarifaBean.item.nome}" >
                        <rich:ajaxValidator event="onblur"/>
                    </h:inputText>
                    <rich:message for="nome" style="color:red" globalOnly="false"/>
                </h:panelGrid>
            </a4j:form>
        </rich:tab>
    </rich:tabPanel>
</a4j:region>
Bean:
private Tarifa item;

    public TarifaBean() {
        dao = new TarifaDAO();
        item = new Tarifa();
    }
...
    public void tarifaChanged(ValueChangeEvent e) {
        item = (Tarifa)e.getNewValue();
        // nunca chega aqui
        System.out.println(" - Tarifa alterada para: "+item.getNome());
    }

Alguém pode me dá um help nisso?

8 Respostas

thiago.correa

Eu não sei qual é o nome agora que o ajax4jsf se uniu com o richfaces, mas no teu select utilize a tag a4j:support, pois ele dispara uma requisição ajax e é capaz de atualizar o teu campo!

D

Olá javer.

Como thiago falou, o a4j:support poderá te ajudar quando for usado dentro da tag do selectOneMenu, mas tipo,

eu tava observando seu selectOneMenu e ele está usando a propriedade reRender, até onde eu sei esta não é uma propriedade do h:selectOneMenu. Se vc necessita usar o reRender (que no seu caso, você vai precisar) acredito que você iria precisar utilizar o

<a4j:support event=“onchange” reRender=“nome” /> dentro da tag selectOneMenu.

abraços, flw

Maurício Esteves

javer

Na verdade não se trata de um campo, mas sim de um formulário inteiro que está linkado a cada propriedade do objeto no BB.

O que você diz a4jsf é:

<a4j:support event="onkeyup" reRender="echo, count" actionListener="#{echoBean.countListener}"/>
Não resolve meu problema.

Obrigado mesmo assim.

javer

dermstr:
Olá javer.

Como thiago falou, o a4j:support poderá te ajudar quando for usado dentro da tag do selectOneMenu, mas tipo,

eu tava observando seu selectOneMenu e ele está usando a propriedade reRender, até onde eu sei esta não é uma propriedade do h:selectOneMenu. Se vc necessita usar o reRender (que no seu caso, você vai precisar) acredito que você iria precisar utilizar o

<a4j:support event=“onchange” reRender=“nome” /> dentro da tag selectOneMenu.

abraços, flw

Maurício Esteves


Obrigado Maurício mas o problema também é que o valueChangeListener="#{tarifaBean.tarifaChanged}" nunca é chamado, por que ocorre isso?

javer

Obrigado a todos,

Como eu havia falado sou iniciante, como tal nem tinha colocado um , agora que coloquei vi que estava dando um erro de conversão.

Estou montando a lista de objeto para mostrar no selectOneMenu assim:
public List<SelectItem> getListaTarifas() {
        dao.load();
        List<SelectItem> l = new ArrayList<SelectItem>();
        Iterator<Tarifa> it = this.getLista().iterator();
        l.add(new SelectItem(0, "- Selecione uma Tarifa -"));
        while (it.hasNext()) {
            Tarifa obj = it.next();
            l.add(new SelectItem(obj.getId(), obj.getNome()));
        }
        return l;
    }
Tenho esse converter, mas acho que tem alguma coisa errada nele ou na forma como estou montando a lista de SelectItem:
public class TarifaConverter implements Converter {

    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        try {
            if (value == null || value.equalsIgnoreCase("0") || value.equalsIgnoreCase("-1")) {
                return null;
            }
            Integer id = new Integer(value);
            return new TarifaDAO().find(id);
        } catch (NumberFormatException ex) {
            throw new ConverterException("Não foi possível converter (" + value + "), não é um número inteiro.", ex);
        } catch (IllegalArgumentException ex) {
            throw new ConverterException("Não foi possível converter (" + value + "), identificador desconhecido.", ex);
        }
    }

    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null) {
            return null;
        }
        if (value instanceof Tarifa) {
            Tarifa tarifa = (Tarifa) value;
            return tarifa.getId().toString();
        } else if (value instanceof String && ((String) value).equalsIgnoreCase("0")) {
            return "0";
        } else {
            throw new ConverterException("A classe " + value.getClass() + " não é uma instância.");
        }
    }
}

Quando coloquei ele como o converter e seleciono um item caiu na throw new ConverterException("A classe " + value.getClass() + " não é uma instância.");

fabio.massa

Olá javer, vamos ver se posso ti ajudar:
A assinatura do método está correta, você debugou e ao alterar o valor do combo seu método não é chamado correto?, bom, o mais indicado como nosso amigos acima disseram era utilizar a tag <a4j:support /> bem mais fácil, mas no seu caso talvez tenha que fazer algo do tipo:

&lt;h:selectOneMenu  
	id="tarifas"  value="#{tarifaBean.item}"  
	valueChangeListener="#{tarifaBean.tarifaChanged}"  
        onchange="document.formTarifasCadastradas.submit();" immediate="true" &gt;  
	&lt;f:selectItems var="tarifa" id="tarifa" value="#{tarifaBean.listaTarifas}" /&gt;  
&lt;/h:selectOneMenu&gt;

Quando comecei com JSF fazia algo do tipo, hoje acho muito mais fácil utilizar a4j.
Tenta aí e fala se deu certo.

Abraços,

javer

Ok, agora tá funcionando.

Só mais uma pergunta: é necessário essa tag <h:form> ?

<h:panelGrid width="100%" columns="2" border="0"> <h:form id="formTarifasCadastradas"> <!-- Lista das Tarifas Cadastradas --> <h:outputLabel for="tarifas" value="Tarifas cadastradas:" style="width:20%" /> <h:selectOneMenu id="tarifas" value="#{tarifaBean.item}" style="width:80%" valueChangeListener="#{tarifaBean.tarifaChanged}" immediate="true" > <f:selectItems var="tarifa" id="tarifa" value="#{tarifaBean.listaTarifas}" /> <a4j:support event="onchange" reRender="formDados" /> <f:converter converterId="ConverterTarifa" /> </h:selectOneMenu> </h:form> </h:panelGrid>

D

Olá javer.

Na minha opinião o h:selectOneMenu está passando valores e valores constituem um formulário.

Então acredito que sim, é necessário. Provavelmente se tirar, ele poderá deixar de funcionar.

Mas qualquer dúvida, faz o teste. Só leva uns segundos :slight_smile:

Até logo.

Maurício Esteves

Criado 4 de junho de 2009
Ultima resposta 4 de jun. de 2009
Respostas 8
Participantes 4