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,