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.

<?xml version="1.0" encoding="utf-8"?>
<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:

<?xml version="1.0" encoding="utf-8"?>
<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.

This movie requires Flash Player 9

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.

Leave a Reply