quarta-feira, 20 de outubro de 2010

Adobe Flex - Setando um item em ComboBox

 Olá a todos. Estou um tempo sem postar pq estou acabando a documentação preliminar do JFERA, framework de integração Java-Flex no Google App Engine.

 Apesar disso, sempre acompanho e respondo questões de Flex no GUJ, que apesar de ser um Fórum Java, é muito bom para qualquer linguagem de programação. Por algumas vezes respondi algumas questões sobre problemas para setar um item em um ComboBox.

 Já passei por esse problema uma vez, quando eu precisava mostrar um formulário de edição de endereço. Nele existiam dois combos, um para estado e outro para cidade. O combo da cidade era dependente do de estado, de forma que seu dataProvider era setado de acordo com o estado escolhido. Na hora de editar o endereço, eu pegava os dados de minha classe de domínio e setava meus campos visuais. Ao setar o estado, tudo funcionava perfeitamente, mas a cidade não.

 Depois de um tempo estudando percebi que da forma que eu fazia as coisas, ocorria o seguinte:

  1.  Eu setava o selecteIndex do combo
  2. Depois de escolhido o estado, eu setava o dataProvider com as respectivas cidades
Me ocorreu então que era provável que ao setar o dataProvider não devia haver uma lógica para conferir se o mesmo continha o objeto já indicado no selectedItem, e por isso que não era mostrado o item corretamente. Pensando nisso, criei um combo personalizado para essas horas:


package br.com.nuccitelli.component {
     import flash.events.Event;
     import mx.binding.utils.BindingUtils;
     import mx.utils.ObjectUtil;
     import spark.components.DropDownList;

     public class DropDowListWithMemory extends DropDownList {
         private var _selectedItemInMemory:Object=null;

         public function DropDowListWithMemory() {
              super();
              BindingUtils.bindSetter(dataProviderHandler,this,[ "dataProvider","length" ]);
         }

         private function dataProviderHandler(obj:Object=null):void {
              if(_selectedItemInMemory) {
                   for each(var item:Object in this.dataProvider) {
                        if(this.equals(item,_selectedItemInMemory)) {
                            this.selectedItem=item;
                            break;
                        }
                   }
              }
         }

         /**
          * The selectedItemInMemory sets selectedItem in 2 ocasions:
          * 1) When you set selectedItemInMemory and data provider has an equals object
          * 2) When dataProvider change and has an object equals to selectedItemInMemory
          **/
         public function get selectedItemInMemory():Object {
              return _selectedItemInMemory;
         }

         /**
          * The selectedItemInMemory sets selectedItem in 2 ocasions:
          * 1) When you set selectedItemInMemory and data provider has an equals object
          * 2) When dataProvider change and has an object equals to selectedItemInMemory
          **/
         public function set selectedItemInMemory(value:Object):void {
              _selectedItemInMemory=value;
              dataProviderHandler();
         }

         private function equals(item:Object,item2:Object):Boolean {
              return ObjectUtil.compare(item,item2)==0;
         }
     }
}


 Também fiz um código unitário, para exemplificar o uso:




package br.com.nuccitelli.component {
     import flexunit.framework.Assert;
     import mx.collections.ArrayCollection;

     public class DropDowListWithMemoryTest {

         [Test]
         public function testSelectedItemWithExistingDataProvider():void {
              var combo:DropDowListWithMemory=new DropDowListWithMemory();
              combo.dataProvider=new ArrayCollection([ "A" , "B" , "C" ]);
              Assert.assertUndefined(combo.selectedItem);
              combo.selectedItemInMemory="B";
              Assert.assertEquals("B" , combo.selectedItem);
         }

         [Test]
         public function testSelectedItemWithOutExistingDataProvider():void {
              var combo:DropDowListWithMemory=new DropDowListWithMemory();
              combo.dataProvider=new ArrayCollection([ "A" , "B" , "C" ]);
              Assert.assertUndefined(combo.selectedItem);
              combo.selectedItemInMemory="D";
              Assert.assertUndefined(combo.selectedItem);
              combo.dataProvider=new ArrayCollection([ "A" , "B" , "C" , "D" ]);
              Assert.assertEquals("D" , combo.selectedItem);
         }
     }
}



Usei o DropDownList, que o combo no Flex 4. Se vc estiver usando o Flex 3, basta trocar o DropDownList por Combo. Para utilizar, basta usar o selectedItemInMemory no lugar do selectedItem.

 Se vc gostou desse post, peço  a gentileza de divulgar o blog bem como os cursos da Nuccitec. Também deixe uma mensagem no blog :)

 Até o próximo post.