[DÚVIDA FLEX] Preenchendo um comboBox a partir do banco de dados

Estou usando java e flex com o blazeDS e surgiu uma dúvida porque eu não sei muito de action script. Como faria
para preencher um combobox a partir de uma lista que vem serviço java?

Opa,

Para fazer uma chamada, considerando que você fará essa chamada utilizando RemoteObject, siga os passos:

[list]Crie uma aplicação Flex[/list]
[list]Declare uma variável que irá armazenar o resultado dentro de um bloco de script. Vou usar users[/list]
[list]Crie um ComboBox. Atribua o dataProvider, utilizando binding, à variável criada no passo anterior. Lembre-se de definir qual a propriedade da coleção que será mostrada no combo, faça isso pela propriedade labelField (no meu exemplo vou utilizar nome)[/list]
[list]Declare um RemoteObject e nele defina o id, destination e as funções que vão tratar os eventos de resultado e falha[/list]
[list]Defina o momento que vai ser chamado o serviço, por exemplo, vou considerar que vai ser clicando em um botão. Neste caso observe o evento click[/list]
[list]Trate o evento click, chamando o servico[/list]
[list]Finalmente atribua o resultado do servidor à variável que foi criada[/list]

Segue exemplo:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
	
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.controls.Alert;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			
			[Bindable]
			private var users:ArrayCollection;
			
			private function onClick():void
			{
				service.listUsers();
			}
			
			private function onResult(event:ResultEvent):void
			{
				users = event.result as ArrayCollection;
			}
			
			private function onFault(event:FaultEvent):void
			{
				Alert.show(event.fault.message, "Erro");
			}
		]]>
	</mx:Script>
	
	<mx:ComboBox dataProvider="{users}" labelField="nome"/>
	
	<mx:RemoteObject id="service" destination="myDestination"
		result="onResult(event)" fault="onFault(event)"/>

	<mx:Button label="chamar serviço" />	
</mx:Application>

[]s,

pow kra brigadao mesmo!

Kra outra dúvida, essa eu vou receber essa lista e vou selecionar um objeto e vou joga-lo na propriedade de outro objeto, como faço? meu form está assim…

<mx:VBox width=“100%” height=“100%”>
<mx:Label text="{message}" fontWeight=“bold” includeInLayout=“false” />
<mx:DataGrid id=“dataGrid” width=“100%” height=“100%” dataProvider="{cargos}"
doubleClickEnabled=“true” doubleClick=“updateCargo()” >
mx:columns
<mx:DataGridColumn dataField=“id” headerText=“ID CARGO” width=“100”/>
<mx:DataGridColumn dataField=“descricao” headerText=“DESCRICAO” />
<mx:DataGridColumn dataField=“departamento” headerText=“DEPARTAMENTO” />
</mx:columns>
</mx:DataGrid>

<mx:ControlBar horizontalAlign=“center”>
<mx:Button label=“Criar cargo” click=“createCargo()” toolTip=“Cria um cargo e o salva no banco de dados.” />
<mx:Button label=“Atualizar cargo” click=“updateCargo()” enabled="{dataGrid.selectedItem}" toolTip=“Atualiza um cargo existente no banco.” />
<mx:Button label=“Deleta cargo” click=“deleteCargo()” enabled="{dataGrid.selectedItem}" toolTip=“Deleta um cargo existente no banco.” />
<mx:Button label="Re-carrega dados " click=“carregaCargos()” toolTip=“Re-carrega a lista de cargos do banco.” />
</mx:ControlBar>
</mx:VBox>

Não sei se entendi bem mais para acessar o objeto selecionado em um datagrid seria:

Isso te retorna a linha selecionada, ou seja, em uma coleção de usuários, isso seria um usuário, então você poderia acessar o nome dele desta forma:

[]s,

Pow kra foi mal postei a pagina errada : eu tenho um VO que será persistido do desse tipo na minha pagina

<vo:Cargo id=“cargo” descricao="{descricaoField.text}" departamento="" />

o meu form (na mesma pagina)

mx:Form>

<mx:FormItem label=“Descricao: " required=“true”>
<mx:TextInput id=“descricaoField” text=”{cargo.descricao}" change=“validateForm(event);” />
</mx:FormItem>

<mx:FormItem label=“Departamento: " required=“false”>
<mx:ComboBox dataProvider=”{departamentos}" id=“departamentoField” />
</mx:FormItem>

</mx:Form>

<mx:ControlBar horizontalAlign=“center”>
<mx:Button label=“Salvar cargo” id=“submitButton” enabled="{formIsValid}" click=“saveCargo();” />
<mx:Button label=“Limpar formulario” enabled="{!formIsEmpty}" click=“clearFormHandler();” />
<mx:Button label=“Cancelar” click=“PopUpManager.removePopUp(this);”/>
</mx:ControlBar>

este comboBox possui uma lista de departamentos, minha dúvida: como faço pra pegar um objeto departamento selecionado no comboBox do meu form e jogar ele no vo Cargo?

Ficaria assim:

[code]<vo:Cargo id=“cargo” descricao="{descricaoField.text}" departamento="{departamentoField.selectedItem as Departamento}" />

<mx:ComboBox dataProvider="{departamentos}" id=“departamentoField” /> [/code]

Ou seja, coloquei um binding para escutar a mudança da linha selecionada do combobox (propriedade selectedItem do combo). O operador “as” é para fazer cast, e só é necessário caso o sua classe Cargo tenha uma prop departamento do tipo Departamento, já que a propriedade selectedItem é um Object (veja na documentação :))

[]s,

Pow kra muito obrigado!

Kra desculpa mais eu to aqui com outra duvida eu tenho esta tabela que lista meus resultados:

esta tabela mostra os cargos e eu queria que ela mostrasse o departamento respectivo de cada cargo. Na tag mx:DataGridColumn eu coloco do dataField desta forma, por que não está correto?

<mx:VBox width=“100%” height=“100%”>
<mx:Label text="{message}" fontWeight=“bold” includeInLayout=“false” />
<mx:DataGrid id=“dataGrid” width=“100%” height=“100%” dataProvider="{cargos}"
doubleClickEnabled=“true” doubleClick=“updateCargo()” >
mx:columns
<mx:DataGridColumn dataField=“id” headerText=“ID CARGO” width=“100”/>
<mx:DataGridColumn dataField=“descricao” headerText=“DESCRICAO” />
<mx:DataGridColumn dataField=“departamento.descricao” headerText=“DEPARTAMENTO” />
</mx:columns>
</mx:DataGrid>

<mx:ControlBar horizontalAlign=“center”>
<mx:Button label=“Criar cargo” click=“createCargo()” toolTip=“Cria um cargo e o salva no banco de dados.” />
<mx:Button label=“Atualizar cargo” click=“updateCargo()” enabled="{dataGrid.selectedItem}" toolTip=“Atualiza um cargo existente no banco.” />
<mx:Button label=“Deleta cargo” click=“deleteCargo()” enabled="{dataGrid.selectedItem}" toolTip=“Deleta um cargo existente no banco.” />
<mx:Button label="Re-carrega dados " click=“carregaCargos()” toolTip=“Re-carrega a lista de cargos do banco.” />
</mx:ControlBar>
</mx:VBox>

Medeiros, de uma olhada na documentação do Flex sobre labelFunction (ctrl+F3 na perspectiva Flex te leva a documentação. Se vc deixar o mouse em cima do DataGrid vai direto para a documentação dele)

Basicamente o labelFunction vai ser uma função que vai ser chamada linha a linha do datagrid para modificar o que você vai apresentar na coluna, ou seja, o labelFunction é por coluna.

Ex.

Tenho uma lista de Usuários e dentro de usuário tenho uma prop cadastrado:Boolean. Gostaria de mostrar sim quando for true e não quando for false, então crio uma labelFunction que vai retornar uma String para ser mostrada nesta coluna do DataGrid.

Outra abordagem seria vc sobrescrever o método toString() (quem vem de Object), na Classe Departamento, e retornar o nome dele ou o que vc deseja apresentar no DG, ai a utilização fica da forma que vc escreveu, só que o dataField=“departamento”

[]s,

Kra li sobre o labelFunction e criei minha função assim:

public function labelDepartamento(item:Object, col:DataGridColumn):String {
return item.descricao; //Aqui esse objeto do tipo Object vem como Cargo ou Departamento? Foi o que eu não entendi bem (lembrando que um cargo possui um departamento)
}

para o datagrid acima, mas eu recebo um erro de null reference como o campo departamento do cargo estivesse vazio, mas quando eu vou no banco lá eu verfico que está cadastrado

Cara, se o datagrid tem uma lista de cargos, vc irá receber um cargo para cada linha do grid.
O cargo nunca poderá ser nulo, pois se for não apareceria uma linha no grid…

Quanto ao labelFuncion seria Cargo(item).departamento.descricao

Ou crie o método toString() na Classe Departamento e retorne descricao

[]s,

Kra eu fiz isso e não funfou…

public function labelDepartamento(item:Object, col:DataGridColumn):String {
return Cargo(item).departamento.descricao;
}

eu recebo este erro:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at org.enovar.view::ListaCargo/labelDepartamento()[C:\Users\Shrek\Desktop\desenvolvimento\flex_jsf\crudFlex\flex_src\org\enovar\view\ListaCargo.mxml:80]
at mx.controls.dataGridClasses::DataGridColumn/itemToLabel()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\dataGridClasses\DataGridColumn.as:1410]
at mx.controls.dataGridClasses::DataGridBase/makeListData()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\dataGridClasses\DataGridBase.as:1328]
at mx.controls::DataGrid/http://www.adobe.com/2006/flex/mx/internal::setupRendererFromData()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\DataGrid.as:1645]
at mx.controls::DataGrid/commitProperties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\DataGrid.as:1608]
at mx.core::UIComponent/validateProperties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5807]
at mx.managers::LayoutManager/validateProperties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:539]
at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:689]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8628]
at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8568]

Coloca um breakpoint na linha que retorna e verifique se o departamento está vindo…

[]s,

Cara debuguei a aplicação e recebi esse erro como se não tivesse conseguindo converter o objeto

TypeError: Error #1034: Type Coercion failed: cannot convert Object@6d987e1 to org.enovar.vo.Departamento.

Você declarou o [RemoteClass(alias=‘pacote.Departamento’] na classe Departamento?

Isso é necessário para converter automaticamente objetos AS <-> Java

Além disso é necessário que vc tenha alguma referência no seu código para esta classe Departamento (cast, variável) para que o compilador inclua esta classe no swf gerado

[]s,

Eu tenho esse [RemoteClass] declarado sim, agora não entendi como fazer para declarar essa referencia para a classe Departamento (cast, variável) no meu código?!

Tipo eu to achando muito estranho pq eu coloquei o breakpoint na assinatura da minha labelFunction aqui:

breakpoint **public function labelDepartamento(item:Object, column:DataGridColumn):String {
return Cargo(item).toString();
}

ele nem ver o resto do codigo e já avisa que tem um erro de conversao…
Como faria no meu código para dizer ao compilador que ele tem que fazer esse cast?

Tente colocar o break na linha de retorno e debuga… se o break sair do lugar significa que vc está com cache. Para garantir que vc está debudando a versão correta, crie um label na tela com uma descrição conhecida…

Sem falar que para evitar esse tipo de coisa, desabilite o cache do browser

[]s,

Outra coisa…

O toString() era no Departamento…

A coluna do datagrid não consegue buscar a descriçao dentro de departamento.descricao. Se vc implementar o toString() em Departamento, o dataField da coluna seria simplesmente departamento, a coluna vai chamar o toString() automaticamente…

Ou vc faz o labelFunction e da return item.departamento.descricao…

[]s,