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.

5 Responses to “Thinking Declaratively with MXML”

  1. Jonathan Branam Says:

    I think the adding columns example is incorrect. You can’t just myGrid.columns.push(…) because the accessor on columns returns a copy of the Array. You need to build another array and then assign it over the columns array.

    var col:Array = myGrid.columns;
    col.push( col );
    myGrid.columns = col;

  2. Kevin Hoyt Says:

    Whoops!

    The code in the article has been updated.

    Thanks,
    Kevin

  3. Abdul Qabiz Says:

    Hi Kevin,

    As usual, a nice post and I also learnt more from this.

    I have been doing some work using html/css/javascript and been following semantic-html and Layer Semantic Markup approach.

    Just wondering, how would you thing semantic in context of mxml? MXML is very powerful because you can have structure as well as style/effects within in it? That surely also causes the bad-apps/design, if best-practices are not considered.

    I have been thinking, how things should have been designed so that RIA applications developed using MXML/ActionScript/CSS can be progressively enhanced or gracefully degraded (for FlashLite etc).

    For example: If there were a subset of MXML to represent semantic/structure of application, another subset to add presentation (CSS is there but limited in some sense) and last subset to add behavior/actions using actionscript..

    It would have been easier to run RIAs on FlashLite by just taking care of presentation and actionscript… Think each part linked as different swfs?

    I might not be making sense, just looking at standards already established and trying to draw some parallels… How can we make one app that works on most of the devices…

    Flex framework needs to separate entire styles related stuff from it’s component, it would become lighter and more flexible?

    I hope, you get the sense… Since you are into both worlds (AJAX/DHTML and Flex), would love to hear your thoughts as a comment or new post :-)

    Thanks

    -abdul

  4. Mrinal Wadhwa Says:

    It’ll be a while before Flex 4 comes out and we get MXMLG but lately I have fallen in complete and utter love with degrafa.

    Over the past month, I’ve been writing all my skins in mxml with degrafa and using markup instead of ActionScript makes the code so easy, intuitive, elegant and beautiful.

    Check this out and you’ll know what I mean

    http://samples.degrafa.com/SphereSkinSample/SphereSkinSample.html

  5. Simon G. Says:

    Thanks Kevin Hoyt for this update!

    Simon G.

Leave a Reply