Preencher ComboBox no Flex Dinamicamente pelo evento CHANGE de outra ComboBox

olá amigos salvadores do GUJ… vcs me ajudam tanto que colocarei no meu projeto, na parte de agradecimento, o nome de vcs… rs

minha duvida agora eh com combobox no flex… na verdade consigo povoar a combo, normal, mas o que quero eh o seguinte… na minha combo Estado, por exemplo, quando selecionar um determinado estado, eu consiga pegar o ID do estado selecionado para depois pegar todas as cidades do estado e povoar uma outra combo…

não estou conseguindo pegar esse parametro, acho q seria o itemIndex, não é? mas quando faço isso, ele da o valor de acordo com a ordem que aparecem na combo… 0,1,2,3… e naum os valores do ID q mando…

mas tudo isso fiz no braço, nada dinamico… mas quero que fique dinamico

então vou postar meus codigos desde a parte java onde crio um list com os estados ateh a chegada dele no flex

[color=red]METODO LISTAR TODOS OS ESTADOS -[/color] farei um select no banco selecionando todos os estados e ordenando pela sigla

public List<Estados> preencherCombo(id int)
	{
		connection = Conexao.conectar();//chamada do método conectar, faz a conexao com o banco
		List<Estados> listaEstados = new ArrayList<Estados>();//instância um objeto do tipo ArrayList		
		try
		{
			statement = connection.createStatement(resultset.TYPE_SCROLL_SENSITIVE, resultset.CONCUR_READ_ONLY);
			statement.executeQuery("SELECT ID_ESTADO, SIGLA_ESTADO FROM PFC_ESTADO ORDER BY SIGLA_ESTADO");
				
			while(resultset.next())//percorre toda a tabela PFC_Estados
			{
				Estados estado = new Estados();//instancia um objeto de Estados
				
				estado.setID(resultset.getInt("ID_ESTADO"));
				estado.setSigla(resultset.getString("SIGLA_ESTADO"));
					
				listaEstados.add(estado);//adiciona o objeto estado na lista
			}	
		}catch(SQLException erro)
		{
			JOptionPane.showMessageDialog(null, "Erro ao listar os dados. "+erro);
	    }
			return listaEstados;//retorna uma lista de objetos de Estados
	}

[color=red]MÉTODO PARA LISTAR TODAS AS CIDADES DE UM ESTADO[/color] - Quando selecionar o estado, o evento change vai chamar um método que selecionará todas as cidades daquele estado escolhido


public List<Cidades> preencherCombo() 
	{
		connection = Conexao.conectar();//chamada do método conectar, faz a conexao com o banco
		List<Cidades> listaCidades = new ArrayList<Cidades>();//instância um objeto do tipo ArrayList
		
		try
		{
			statement = connection.createStatement(resultset.TYPE_SCROLL_SENSITIVE, resultset.CONCUR_READ_ONLY);
			statement.executeQuery("SELECT ID_CIDADE, NOME_CIDADE FROM PFC_CIDADE WHERE IDESTADO_CIDADE="+id+" ORDER BY NOME_CIDADE");
			
			while(resultset.next())
			{
				Cidades cidade = new Cidades();//instancia um objeto de Cidades
				
				cidade.setID(resultset.getInt("ID_CIDADE"));
				cidade.setNome(resultset.getString("NOME_CIDADE"));
				
				listaCidades.add(cidade);////adiciona o objeto cidade na lista
			}
		}catch(SQLException erro)
		{
            JOptionPane.showMessageDialog(null, "Erro ao listar itens da combo box. "+erro);
		}
		return listaCidades;//retorna uma lista de objetos de Cidades
	}

[color=red]COMBO NO FLEX[/color] - minhas duas comboBox

<mx:ComboBox id="comboEstados" change="{listarCidades()}"></mx:ComboBox>

<mx:ComboBox id="comboCidades" ></mx:ComboBox>

[color=red]FUNCTIONS QUE SERVIRÁ PARA CHAMAR OS MÉTODOS JAVA E PREENCHER AS COMBO[/color]


    		[Bindable]
    		  private var estados:ArrayCollection;
                  private var cidades:ArrayCollection;

                //chamo esse metodo para listar todos os estados
                public function listaComboEstado():void
    		{
    			DAOEstado.listarCombo();
    		}
    		//Com o que retorna do java preencho a combo
    		public function ResultadoListaComboEstado(event:ResultEvent):void
    		{
    			estados = event.result as ArrayCollection;

                        comboEstados.dataProvider = estados;
    		}

                //chamo a funçao para preencher todas as cidades de um determinado estado
               //passando o ID do estado escolhido
                public function listaComboCidades():void
    		{
                        //acho q o parametro ficaria assim, para passar para o listarComboCidades
    			DAOCidades.listarCombo(comboEstado.selectedIndex);
    		}
    		
    		public function ResultadoListaComboCidade(event:ResultEvent):void
    		{
    			cidades = event.result as ArrayCollection;

                        comboCidades.dataProvider = cidades;
    		}

Amigos, se puderem me ajudar, agradecerei muito

Abraços

Cara… vc vai ter q implementar um model pra esta list ai… Dai vc cria um bean estado que tem ID + Descricao… e trata o model pra retornar o toString() soh como descricao… Bom… dai vc trata como quiser… nao sei se da pra fazer isso ai mas acho q seria a melhor maneira… veja como fiz em J2SE com meus Beans pra fazer um model personalizado de uma Jtree

package TableModelsPersonalizados;

import MyBeans.*;
import commun.BDConection;
import commun.MyLogger;
import commun.SqlConstants;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

public class MyTreeModel implements TreeModel {

    private List<TreeModelListener> listeners = new ArrayList<TreeModelListener>();
    private List<Classe_Membros> classe_membros;

    public MyTreeModel(){
        this.classe_membros = this.getClasseMembros();
    }

    public MyTreeModel(List<Classe_Membros> classe_membros) {
        this.classe_membros = classe_membros;
    }

    public Object getChild(Object parent, int index) {
        if (parent == classe_membros) {
            return classe_membros.get(index);
        }

        if (parent instanceof Classe_Membros) {
            return ((Classe_Membros) parent).getMembros().get(index);
        }

        throw new IllegalArgumentException("Invalid parent class" + parent.getClass().getSimpleName());
    }

    public int getChildCount(Object parent) {
        if (parent == classe_membros) {
            return classe_membros.size();
        }

        if (parent instanceof Classe_Membros) {
            return ((Classe_Membros) parent).getMembros().size();
        }

        throw new IllegalArgumentException("Invalid parent class" + parent.getClass().getSimpleName());
    }

    public int getIndexOfChild(Object parent, Object child) {
        if (parent == classe_membros) {
            return classe_membros.indexOf(child);
        }
        if (parent instanceof Classe_Membros) {
            return ((Classe_Membros) parent).getMembros().indexOf(child);
        }

        return 0;
    }

    public Object getRoot() {
        return classe_membros;
    }

    public Classe_Membros getLeafsDad(Object m) {

        if (m instanceof Classe_Membros) {

            return (Classe_Membros) m;

        } else if (m instanceof Membros) {
            Membros t = (Membros) m;

            for (int i = 0; i < classe_membros.size(); i++) {
                if (classe_membros.get(i).getId() == t.getId_classe()) {
                    return classe_membros.get(i);
                }
            }
        }

        return null;

    }

    public boolean isLeaf(Object node) {
        return node instanceof Membros;
    }

    public void valueForPathChanged(TreePath path, Object newValue) {
    }

    public void removeTreeModelListener(TreeModelListener l) {
        listeners.remove(l);
    }

    public void addTreeModelListener(TreeModelListener l) {
        listeners.add(l);
    }

    public List<Classe_Membros> getClasseMembros() {
        List<Classe_Membros> classes = new ArrayList();

        try {
            Connection con = new BDConection().getCon();
            PreparedStatement stm = con.prepareStatement(new commun.SqlConstants().getSQL(SqlConstants.DESCRIPTION));

            ResultSet rs = stm.executeQuery();

            while (rs.next()) {
                Classe_Membros nova_classe = new Classe_Membros();

                nova_classe.setId(rs.getInt("id"));
                nova_classe.setDesc(rs.getString("descricao"));

                int id = nova_classe.getId();

                PreparedStatement stm2 = con.prepareStatement(new commun.SqlConstants().getSQL(SqlConstants.MEMBROS_DA_CLASSE));

                stm2.setInt(1, id);

                ResultSet rs2 = stm2.executeQuery();

                while (rs2.next()) {
                    Membros novo_membro = new Membros();

                    novo_membro.setId(rs2.getInt("id"));
                    novo_membro.setDesc(rs2.getString("descricao"));
                    novo_membro.setId_classe(id);

                    nova_classe.addMembro(novo_membro);
                }

                classes.add(nova_classe);

            }

            return classes;

        } catch (Exception e) {
            String msg = "Erro ao gerar Bean List";

            JOptionPane.showMessageDialog(null, msg);

            new MyLogger(msg, e);
        }

        return classes;
    }
}

Olá Vinicius… blz?

Cara, até entendi o que disse, mas qual a diferença em criar um Model e um list de uma classe?? o problema não seria o modo como irei atribuir esses valores na Combo do Flex??

vamos la.

Primeiro vamos começar pela suas classes java. Elas estão ok, tirando por 1 linha:

no método que lista todas as cidades de um estado vc tem essa linha:

de onde vem esse id? Acho que esta faltando um parametro no metodo. A assintatura entao deveria ser algo do tipo public List preencherCombo(Integer id).


Agora vamos pro flex.

Primeiro uma correção, que todo mundo faz quando começa com flex. Nos handles de evento, não é necessário colocar as “{}” por tanto tente usar sempre algo:

Agora voltando a lógica, ela está correta, o que falta ai é criar o método listarCidades() que fará a seguinte rotina:

public function listaCidades():void { DAOEstado.listarCombo(comboEstados.selectedItem.ID); }

O que eu fiz aqui foi, eu peguei o combo de estados (comboEstados) e peguei o item selecionado e passei o atributo ID para a chamada do método. Lembrando que eu não tenho certeza se esse ID é todo maiusculo. (acho que sim baseado pelo set da classe java).
Agora como o resto foi estruturado e como vc pega o resultado de sua chamada eu desconheço, então dai pra frente é contigo. =)

E ai… blz??? A vantagem do model é q vc pode model[a-lo de acordo com sua necessidade… no seu caso qdo vc pegar o valor do combo vc pode customizar o model para voltar o ID q vc precisa e não o Estado… Assim vc popula o outro box como quiser…

Olá Bruno.

Quanto ao metodo realmente a assinatura estava errada… não percebi isso enquanto postava…

bom, num teste q fiz de flex pra flex funciona perfeitamente, mas quando coloco o java na parada não aparece nada. A combo fica vazia… tem alguma coisa a ver se os atributos são publicos ou privados?? fiz até uma alteração nas minhas classes quanto a isso e nada … msm colocando tudo como publico não aparece nada tbm… naum acusa nenhum erro tbm… simplesmente não preenche a combo

Abaixo mostro como faço a chamado do metodo, como trato o result e o fault…

private var listEstados:ArrayCollection;

public function encherComboEstado():void
{
	Controle.encherCombo();
}
public function resultadoEncheCombo(event:ResultEvent):void
{
	listEstados = event.result as ArrayCollection;
	comboEstado.dataProvider = listEstados;
}
public function erroCombo(event:FaultEvent):void
{
	Alert.show(event.fault.faultString);
}

e a combo ficou assim

		<mx:ComboBox x="376" y="309" width="67" id="comboEstado" dataProvider="{listEstados}" labelField="sigla"></mx:ComboBox>

não consegui encontrar erro nisso… há algum??

valeu msm amigo

Perfeito. Achei o erro amigo… Burrice minha pacas… Quando mandava pro Controle chamar a DAO, fazia meu controle retornar VOID … rsrsrsrsrsrsrs… ai naum há combo no mundo q mostraria algo…rsrsrsrs

Mas amigo, agora pra variar surge outro problema… seguinte, quando retorno do banco um registro qualquer (Cliente)… o cara mora num estado. Como faço minha combo ficar marcada com o estado que está registrado no Banco?

Pessoal, só aproveitando o topico, pq ja procurei aqui e nao sei se procurei pouco ou se nao tem mesmo
mas alguem roda Flex + Java com glassfish?

pq eu tentei umas coisas e só consegui rodar com tomcat

isso no blazeds

Se voce tiver usando entidades preenchendo a combo com uma entidade voce pode criar um metodo assim para achar o indice no arraycollection:

public static function getIndexInCollection(array:ArrayCollection, obj:#Entidade#):int{ if((array == null) || (obj == null)) return -1; if(array != null){ if(obj != null){ for(var i:int=0; i<array.length; i++){ if((#Entidade#(array[i]).#IDEntidade# == obj.#IDEntidade#)){ return i; } } } } return -1; }

Dai vc da um combobox.selectedIndex = getIndexInCollection(seuArrayDataProvider, Objeto);
Se nao vc faz um for each(var a:String in ArrayCollection) for(var i:int=0;i<arraycollection.leght();i++) if(a == arraycollection[i]) return i

Olá Pedro… blz??

cara, funcionou o jeito que me passou… muito grato… mas ele só funciona quando uso um array feito pro proprio AS… as combos que faço dessa forma estão puxando perfeito…

tenho um array de estado civil feito no AS

public function preencherComboEstCivil():ArrayCollection
{
	var estCivil:ArrayCollection = new ArrayCollection();
	
	estCivil.addItem({estCivil:"Casado"});
	estCivil.addItem({estCivil:"Divorciado"});
	estCivil.addItem({estCivil:"Solteiro"});
	estCivil.addItem({estCivil:"Viúvo"});
	
	return estCivil;	
}

E em certo momento quando qro deixar a combo com a opçao salva no banco… se solteiro, uso a rotina abaixo.

//setar combo de acordo com o registro gravado no banco

for (var i:int=0;i<listaComboEstCivil.length;i++)
		if (listaComboEstCivil[i].estCivil == gridCliente.selectedItem.estadoCivil)
			comboEstadoCivil.selectedIndex = i;

comparo com o gridCliente.selectedItem pois meu arrayCollection de pesquisa de cliente q o java devolve vai para o dataProvider desse grid… Isso funciona perfeito

mas meu problema está sendo com os arrays que o flex recebe do java… tipo o de estado… no DAOEstado tenho um metodos chamado preencherCombo que faz o seguinte

	public List preencherCombo() throws SQLException,Exception
	{
		connection = Conexao.conectar();//chamada do método conectar, faz a conexao com o banco
	
		List listaEstados = new ArrayList();//instância um objeto do tipo ArrayList		
		[code]
			statement = connection.createStatement(resultset.TYPE_SCROLL_SENSITIVE, resultset.CONCUR_READ_ONLY);
			resultset = statement.executeQuery("SELECT ID_ESTADO, SIGLA_ESTADO FROM PFC_ESTADOS ORDER BY SIGLA_ESTADO");
			
			while(resultset.next())//percorre toda a tabela PFC_Estados
			{	
				HashMap estados = new HashMap();
				estados.put("codigo", resultset.getString("ID_ESTADO"));
				estados.put("sigla", resultset.getString("SIGLA_ESTADO"));
				
				listaEstados.add(estados);//adiciona o objeto estado na lista
			}		
		return listaEstados;//retorna uma lista de objetos de Estados
	}

Seleciona todos os estados do banco, monta o map e coloca num array que será retornado ao Flex…

Mas quando tento fazer a msm coisa que faço com estado civil ele não faz. Se peço pra que ele me mostre o lenght desse array num Alert.Show ele já não executa nada q esteja desse alert para baixo…

recebo o resultado do java da seguinte forma abaixo

public function resultadoEncheCombo(event:ResultEvent):void
{
			listaComboEstado = event.result as ArrayCollection;
			comboEstado.dataProvider = listaComboEstado;
			comboEstado.labelField = "sigla";
			preencherCombo("cidade");	
}

ai para tentar setar a combo conforme o estado que foi gravado no registro de um cliente, como minha pesquisa fica numa grid, eu comparo o codigo do array listaComboEstado com o gridCliente.selectedItem.estado …

for (var i:int=0;i<listaComboEstado.length;i++)
		if (listaComboEstado[i].codigo == gridCliente.selectedItem.estado)
			comboEstado.selectedIndex = i;

mas nada acontece… jah tentei colocar antes de começar esse for um Alert.show(listaComboEstado.lenght) mas não funciona… nenhuma msg vai a tela… quando consegui imprimir esse lenght, ele acusa 0… ai nem entra no loop…

tem um motivo para isso ocorrer?? teria uma outra forma de fazer isso??

desde já muito grato

Não deu pra eu ver nos minimos detalhes seu codigo mais dei uma olhada por cima.
Ai vai algumas dicas de boas praticas nessas situações.

tenta fazer um cast para o tipo de dado que voce quer na hora de comparar. ex:

for (var i:int=0;i<listaComboEstado.length;i++)   
        if (Estado(listaComboEstado[i]).codigo == Estado(gridCliente.selectedItem).codigo)   
//NESSAS SITUAÇÕES É MELHOR COMPARAR CHAVE COM CHAVE
            comboEstado.selectedIndex = i;  

Coloca um breakpoint no resulthandler e ve o conteudo da variavel evt.result para ver se ta vindo os dados do java.
Se tiver vindo do java não tem porque o array ta vazio.

junior.gnc,

Sugiro que você dê olhada em um framework chamado Cairngorm e um padrão de projeto chamado ModelLocator. Numa boa, seu código não está legal e vai ser difícil dar manutenção nele e modificar, inclusive controlar essas coisas básicas que precisa. Usando o Cairngorm e esse padrão te ajudaria MUITO.

E sugiro também que use o Hibernate.

[]'s

Olá AUser,

Vou dar uma olhada sim valeu pela dica.
E eu já uso Hibernate. Na verdade estou brincando com flex faz uns 4 meses e não tive tempo de estudar mto. Pois estou trabalhando com ele ja desdo primeiro dia que eu comecei.
Eu sei que não é a melhor maneira de se desenvolver mais no momento é o que eu tenho.

Ô Pedro,

Me desculpa rapaz, errei a destinação. rsrsrs. Era pro dono do tópico isso. O junior.gnc.

Eu acabei errando o destinatário aqui, rs. Desculpas.

[]'s

Ah, ^^ hehe
de boa.
Fiquei imaginando porque meu codigo tava tao ruim assim hehe.

Penso diferente do AUser. Como você está começando com flex, não se fixe a frameworks, não agora. Deixe o Caringorm de lado até que você tenha um conhecimento legal no flex.

Quando começar a se incomodar com o código, ou quando este não lhe atender mais, faça um refactoring e mude para algum framework, sugiro a você Mate ou Swiz, são frameworks mais ágeis e menos burocráticos que o Cairngorm, o que vai facilitar a sua vida e não causar problemas.

[quote=Bruno Sales]Penso diferente do AUser. Como você está começando com flex, não se fixe a frameworks, não agora. Deixe o Caringorm de lado até que você tenha um conhecimento legal no flex.

Quando começar a se incomodar com o código, ou quando este não lhe atender mais, faça um refactoring e mude para algum framework, sugiro a você Mate ou Swiz, são frameworks mais ágeis e menos burocráticos que o Cairngorm, o que vai facilitar a sua vida e não causar problemas.[/quote]

E também penso diferente, Bruno, rs.

Acho melhor para aprendizado começar com algo mais difícil, mais burocrático, e depois sentir o gosto do alívio em usar um Swiz da vida.

O problema de aprender Flex sem regras (e isso eu pude acompanhar com todos que vi) é que no futuro ela vai cometer os mesmos códigos. Fica um pouco diferente, óbvio, mas não fica tão bom assim. Ao menos é a minha opinião.

Refactoring em alguns casos deixa mais trabalhoso. As vezes compensa mais jogar fora e começar do zero. Mas de toda forma, me referi mais aquelas Strings de SQL. Refactoring disso? Não tem como, só pegar o hibernate e fazer novamente.