Template Components in Flex4
Template Components can be quite common in different sort of applications. Maybe the most common one is the Panel, which has a predefined set of components (title bar, status bar, close button, etc) and an specific area where we can instantiate any other component we wish.
In Flex3 you could use the technique explained in the Flex documentation in combination with [DefaultProperty] metadata. The technique basically consists in creating a subclass of a Container component who defines properties with a general data type that lets the component user specify an object of a concrete data type and then reparents it.
Flex4 Skins, by definition, serve the purpose of a templating system. If you consider the example of a s:Panel you have the PanelSkin where you can really easily change and adapt the template and where and how the provided / customizable content will be placed.
If you have to create a templated component with just one customizable area, maybe the best approach to create it would be to use an s:SkinnableComponent. In the following example I’ve created a very simple template that places a header an a footer around a given component.
<s:Application
minWidth="955" minHeight="600"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:local="*">
<s:layout>
<s:VerticalLayout
horizontalAlign="center"
verticalAlign="middle"/>
</s:layout>
<s:SkinnableContainer
width="200" height="200"
skinClass="TemplateSkin1">
<local:MyComponent
width="100%" height="100%"
backgroundColor="0xff0000"/>
</s:SkinnableContainer>
<s:SkinnableContainer
width="200" height="200"
skinClass="TemplateSkin1">
<local:MyComponent
width="100%" height="100%"
backgroundColor="0x00ff00"/>
</s:SkinnableContainer>
</s:Application>
Where TemplateSkin1 is:
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
alpha.disabled="0.5"
xmlns:local="*">
<fx:Metadata>
<![CDATA[
[HostComponent("spark.components.SkinnableContainer")]
]]>
</fx:Metadata>
<s:states>
<s:State name="normal"/>
<s:State name="disabled"/>
</s:states>
<s:layout>
<s:VerticalLayout gap="0"/>
</s:layout>
<local:Bar
width="100%"
text="Header"/>
<s:Group id="contentGroup"
width="100%" height="100%"
minWidth="0" minHeight="0">
<s:layout>
<s:BasicLayout/>
</s:layout>
</s:Group>
<local:Bar
width="100%"
text="Footer"/>
</s:Skin>
The SkinnableContainer base class provides a series of functionalities like creationPolicy and layout property proxying or deferred instantiation that makes very easy the task of creating templated components.
See sample fullScreen
Browse code.
In more complex scenarios where the template has more than one customizable area SkinnableContainer might not be the best choice. You can find further information about this scenario in the DualPanel component post.
