Thinking Declaratively with MXML

There’s no mistaking that Flex 2 has been a historic release in the evolution of the framework. With Flex 3 closing in fast, there’s even more great features we can now use in our applications. Sometimes however, it is important to go back a remember some of the smaller features we may be overlooking. On a recent project I was reminded of the beauty of MXML itself, and the simple elegance that is markup.

MXML is one of those fundamentals of Flex that can sometimes catch developers off guard. The key is to remember that for the most part, every MXML tag and attribute corresponds directly to a Flex class and property respectively. When you declare , what you’re really doing is instantiating an instance of the DataGrid class. Any attributes you set on the tag become property assignments.

Note that there are exceptions such as , which you might use for item renderers, or which you might use to describe your data model (especially for validation).

With that in mind, your assignment is to create a Canvas that has a DropShadowFilter on it at startup. You might think of a few ways to manage this task. The first solution that comes to most peoples minds is to catch the creationComplete event and then create and assign an instance of the filter. The second is to do the same steps, but all inline. These approaches will look something like the following snippet.

<mx:Script>
import flash.filters.DropShadowFilter;

public function doCreationComplete( event:Event ):void
{
    myCanvas.filters = new Array( new DropShadowFilter() );
}
</mx:Script>

...

<mx:Canvas id="myCanvas" creationComplete="doCreationComplete( event )" />

Thinking declaratively however, it is important to remember that attributes of a tag are properties of a class. In this respect, why can’t we declare the “filters” property using MXML? Further, why not create an instance of DropShadowFilter declaratively as well. While we’re at it, we can even set all the filter properties declaratively. This approach looks something like the following snippet.

<mx:Canvas>
    <mx:filters>
        <mx:Array>
            <mx:DropShadowFilter blurX="3" blurY="6" color="0x000000" />
        </mx:Array>
    </mx:filters>
</mx:Canvas>

If after reading these code samples, you find yourself thinking that this is obvious, rest assured that I’ve seen even the best Flex developers jump through hoops to solve a problem in script that might have otherwise been accomplished declaratively. In looking back through some of my own past code, I’ve even seen places where I’ve use the script approach where the declarative approach made more sense.

Okay, so where are some other areas where thinking declaratively can really make a big difference?

Probably the next most common situation where I see script being used where MXML would work better is when developers use the Flex charting. The Flex charts (improved in Flex 3) provide a wealth of flexibility in the appearance. Strokes, fill, axes, series are all classes that can be creatively declaratively just as easily as they can be through script.

<mx:CartesianChart id="chart" width="100%" height="100%">
    <mx:horizontalAxis>
        <mx:DateTimeAxis
            id="dAxis"
            displayName="Time"
            autoAdjust="{adjust.selected}"
            displayLocalTime="{local.selected}"  />
    </mx:horizontalAxis>
    <mx:horizontalAxisRenderer>
        <mx:AxisRenderer
            minorTickPlacement="outside"
            minorTickLength="3">
            <mx:minorTickStroke>
                <mx:Stroke color="#BBCCDD" weight="1" />
            </mx:minorTickStroke>
        </mx:AxisRenderer>
    </mx:horizontalAxisRenderer>
    <mx:dataProvider>{dataSet}</mx:dataProvider>
        <mx:series>
        <mx:ColumnSeries
            displayName="Bannana Sales"
            xField="dt"
            yField="F0" />
    </mx:series>
</mx:CartesianChart>

What is interesting is that it is equally common to find developers having problems going the other way - making the connection between all those tags and the class/properties they represent. As an example, I’ve often been asked how to add columns to a DataGrid from script. This is usually because the developer has disconnected the markup from the class.

<mx:Script>
...
import mx.controls.dataGridClasses.DataGridColumn;

public function doCreationComplete( event:Event ):void
{
	var cols:Array = new Array();
	var col:DataGridColumn = null;

	for( var c:Number = 0; c < 5; c++ )
	{
		col = new DataGridColumn();
		col.headerText = "Stuff " + c;

		cols.push( col );
	}

	grid.columns = cols;
}
...
</mx:Script>

...

<mx:DataGrid id="myGrid" creationComplete="doCreationComplete( event )" />

Finally, I’ll leave you with a somewhat more fringe case, that has application nonetheless. How do you apply a mask to a display object? There’s clearly a mask property, but how does that manifest itself in markup? In the following example, I’ve applied a mask object via MXML.

<mx:Canvas width="100" height="100" mask="{myMask}" />

<mx:Canvas id="myMask" width="100" height="100" borderSkin="skins.MyStarMaskSkin" />

What’s particularly interesting is that the only script is in drawing the border skin of the mask object. There’s been some discussion of the forthcoming MXMLG, which I think really starts to make the declarative side of Flex even more compelling. In the meantime, I encourage you to step back occasionally, and think about what the humble feature of MXML can do for you.

WordPress database error: [Can't open file: 'wp_comments.MYI' (errno: 145)]
SELECT * FROM wp_comments WHERE comment_post_ID = '141' AND comment_approved = '1' ORDER BY comment_date

Leave a Reply