Saturday, March 22, 2014

Flex 4: Accessing the renderers of a DataGroup

There might be situations where you might be creating a list of items in a horizontal or vertical manner. And you might be using a <DataGroup> to get things done. But after you have successfully created a list, you might have to disable 1 of the items, but how are you going to access the individual items of the <DataGroup>? I hope that this post would give an idea on how do access the individual item of a <DataGroup>.

Source Code for the main application - 'SimpleDataGroup.mxml'
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" 
      xmlns:mx="library://ns.adobe.com/flex/mx" 
      width="100%" 
      height="100%" 
      creationComplete="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import events.RendererEvent;
   
   import mx.collections.ArrayCollection;
   import mx.events.FlexEvent;
   
   import renderers.HorizontalRenderer;
   import renderers.VerticalRenderer;
   
   private var dataArray:Array = [{
    label: 'Item 1',
    value: 'A'
   },{
    label: 'Item 2',
    value: 'B'
   },{
    label: 'Item 3',
    value: 'C'
   },{
    label: 'Item 4',
    value: 'D'
   },{
    label: 'Item 5',
    value: 'E'
   },{
    label: 'Item 6',
    value: 'F'
   },{
    label: 'Item 7',
    value: 'G'
   },{
    label: 'Item 8',
    value: 'H'
   }];
   
   //Our Data
   [Bindable]
   private var dataCollection:ArrayCollection = 
    new ArrayCollection(dataArray);
   
   //This will be our simple result text string.
   [Bindable]
   private var resultStr:String = "";
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    this.addEventListener(RendererEvent.RENDERER_CLICK_EVENT,
     clickEvent);
   }
   
   //Upon clicking on one of the buttons, we will loop through
   //all the buttons in the DataGroup and change their state
   //accordingly.
   private function clickEvent(event:RendererEvent):void
   {
    var tempHRenderer:HorizontalRenderer;
    var tempVRenderer:VerticalRenderer;
    for(var i:int = 0; i < hData.numElements; i ++)
    {
     tempHRenderer = 
      HorizontalRenderer(hData.getElementAt(i));
     if(tempHRenderer.data.label == event.label)
     {
      tempHRenderer.currentState = "selected";
     }else{
      tempHRenderer.currentState = "init";
     }
    }
    for(i = 0; i < vData.numElements; i ++)
    {
     tempVRenderer = 
      VerticalRenderer(vData.getElementAt(i));
     if(tempVRenderer.data.label == event.label)
     {
      tempVRenderer.currentState = "click";
      resultStr = "You have click on the button " +
       "labeled '" + tempVRenderer.data.label + 
       "' with a value of '" + 
       tempVRenderer.data.value + "'";
     }else{
      tempVRenderer.currentState = "norm";
     } 
    }
   }
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%" 
     horizontalAlign="center" 
     verticalAlign="middle">
  <s:Label text="Try clicking on a button."/>
  <s:DataGroup width="100%" 
      id="hData"
      dataProvider="{dataCollection}"
      itemRenderer="renderers.HorizontalRenderer">
   <s:layout>
    <s:HorizontalLayout gap="0" 
         verticalAlign="middle" 
         horizontalAlign="center"/>
   </s:layout>
  </s:DataGroup>
  <s:DataGroup width="100%"
      id="vData"
      dataProvider="{dataCollection}"
      itemRenderer="renderers.VerticalRenderer">
   <s:layout>
    <s:VerticalLayout gap="0"
          verticalAlign="middle" 
          horizontalAlign="center"/>
   </s:layout>
  </s:DataGroup>
  <s:Label text="{resultStr}"/>
 </s:VGroup>
</s:Application>

And here's the custom event class for the renderers - 'RendererEvent.as'
package events
{
 import flash.events.Event;
 
 public class RendererEvent extends Event
 {
  //We will dispatch this event when we 
  //click on a renderer.
  public static const RENDERER_CLICK_EVENT:String = 
   "RenderClickEvent";
  
  //Used to stores the label 
  public var label:String = "";
  
  public function RendererEvent
   (type:String, 
    bubbles:Boolean=false, 
    cancelable:Boolean=false, 
    _label:String="")
  {
   super(type, bubbles, cancelable);
   label = _label;
  }
  
  override public function clone():Event
  {
   return new RendererEvent(type, 
    false, 
    false, 
    label);
  }
 }
}

And here's the horizontal item renderer - 'HorizontalRenderer.mxml'
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    autoDrawBackground="true" 
    mouseChildren="false" 
    click="clickHandler(event)" 
    buttonMode="true">
 
 <fx:Script>
  <![CDATA[
   import events.RendererEvent;
   
   //When we click on this Renderer, 
   //we will dispatch an event.
   protected function clickHandler(event:MouseEvent):void
   {
    this.dispatchEvent(
     new RendererEvent(
      RendererEvent.RENDERER_CLICK_EVENT, 
      true, 
      false, 
      this.data.label));
   }
  ]]>
 </fx:Script>
 <s:states>
  <s:State name="init"/>
  <s:State name="selected"/>
 </s:states>
 <s:BorderContainer height="30" 
        width="80">
  <s:backgroundFill.init>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFFF"/>
    <s:GradientEntry color="0xCCCCCC"/>
   </s:LinearGradient>
  </s:backgroundFill.init>
  <s:backgroundFill.selected>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFCC"/>
    <s:GradientEntry color="0xCCFF99"/>
   </s:LinearGradient>
  </s:backgroundFill.selected>
  <s:borderStroke> 
   <mx:SolidColorStroke 
    color="black" 
    weight="1"/> 
  </s:borderStroke>
  <s:VGroup width="100%" 
      height="100%"
      horizontalAlign="center"
      verticalAlign="middle">
   <s:Label text="{data.label}"
      color="0x000000"/>
  </s:VGroup>
 </s:BorderContainer>
</s:ItemRenderer>

And here's the vertical item renderer - 'VerticalRenderer.mxml'
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    autoDrawBackground="true" 
    mouseChildren="false" 
    click="clickHandler(event)" 
    buttonMode="true">
 
 <fx:Script>
  <![CDATA[
   import events.RendererEvent;
   
   //When we click on this Renderer, 
   //we will dispatch an event.
   protected function clickHandler(event:MouseEvent):void
   {
    this.dispatchEvent(
     new RendererEvent(
      RendererEvent.RENDERER_CLICK_EVENT, 
      true, 
      false, 
      this.data.label));
   }
  ]]>
 </fx:Script>
 <s:states>
  <s:State name="norm"/>
  <s:State name="click"/>
 </s:states>
 <s:BorderContainer height="30" 
        width="80">
  <s:backgroundFill.norm>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xCCCCCC"/>
    <s:GradientEntry color="0x666666"/>
   </s:LinearGradient>
  </s:backgroundFill.norm>
  <s:backgroundFill.click>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xCCFFFF"/>
    <s:GradientEntry color="0x00FFCC"/>
   </s:LinearGradient>
  </s:backgroundFill.click>
  <s:borderStroke> 
   <mx:SolidColorStroke 
    color="black" 
    weight="1"/> 
  </s:borderStroke>
  <s:VGroup width="100%" 
      height="100%" 
      horizontalAlign="center" 
      verticalAlign="middle">
   <s:Label text="{data.label}"
      color.norm="0xFFFFFF"
      color.click="0x000000"/>
  </s:VGroup>
 </s:BorderContainer>
</s:ItemRenderer>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

No comments:

Post a Comment