Monday, March 23, 2009

Template Components

This is not a complex topic, but there are lot of Flex developers that never used or don't even know about template components. Template components are unique type of components where the variables are typed in a more general way, allowing for flexibility in design. Let's say we want to have a panels of news. Each panel should contain one news. Each news has it's title which is simple label, it's footer which is some link and content. While the title and footer are always label and link the content can be very different e.g. it can be photo for one news, just a text or some voting for another one. But we didn't want to have different custom components for each of this types. So here where we can use template components. See in the following example.

Source

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:ns1="*"
 layout="vertical">

 <ns1:NewsPanel title="Hockey">
  <ns1:newsTitle>
   <mx:Label text="Ryan Miller returns" color="red" fontWeight="bold" />
  </ns1:newsTitle>
  <ns1:content>
    <mx:Image source="http://fan.violescent.net/enthness/affiliates/smyth/5_ryanmiller.jpg"/>
  </ns1:content>
  <ns1:footer>
   <mx:LinkButton label="Other Photos..." />
  </ns1:footer>
 </ns1:NewsPanel>
 
 <ns1:NewsPanel title="Hockey">
  <ns1:newsTitle>
   <mx:Label text="A costly meltdown" color="red" fontWeight="bold" />
  </ns1:newsTitle>
  <ns1:content>
    <mx:Text text="The Panthers were less than three minutes away from sliding into a playoff position Saturday night."
     truncateToFit="true" width="225" />
  </ns1:content>
  <ns1:footer>
   <mx:LinkButton label="Details..." />
  </ns1:footer>
 </ns1:NewsPanel>
 
</mx:Application>

NewsPanel.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
 initialize="init()" width="250">
 
 <mx:Script>
  <![CDATA[
   import mx.controls.Label;
   import mx.controls.LinkButton;
   import mx.core.UIComponent;
   
   // An array which stores the UI components
   // of our content
   [ArrayElementType("mx.core.UIComponent")]
   private var _content:Array;
   
   private var _footer:LinkButton;
   private var _newsTitle:Label;
   
   
   public function init():void
   {
    this.addChild(_newsTitle);
    
    for each(var component:UIComponent in _content)
    {
     this.addChild(component);
    }
    
    this.addChild(_footer);
   }
   
   public function set newsTitle(value:Label):void
   {
    _newsTitle = value;
   }
   
   public function get newsTitle():Label
   {
    return _newsTitle;
   }
   
   public function set footer(value:LinkButton):void
   {
    _footer = value;
   }
   
   public function get footer():LinkButton
   {
    return _footer;
   }
   
   public function set content(value:Array):void
   {
    _content = value;
   }
   
   public function get content():Array
   {
    return _content;
   }
  ]]>
 </mx:Script>
 
</mx:Panel>