Monday, November 19, 2007

MXML Vs. ActionScript: Properties, Events, Effects, and Styles Declarations

The Adobe Flex documentation describes the Relationship of MXML Tags to ActionScript Classes (livedocs.adobe.com/flex/201/html/mxml_013_4.html). Essentially each MXML tag (an XML tag conforming to the MXML grammar) corresponds to an ActionScript class. However, not every ActionScript class in the Flex framework (classes in a package starting with mx) has a corresponding MXML tag and, of course, the Flash API ActionScript classes (classes in packages beginning with flash) also do not have MXML counterparts. Examples of Flex ActionScript classes that do not have MXML counterparts include mx.controls.Alert, mx.utils.StringUtil, mx.utils.ObjectUtil, and the mx.logging classes.

Conversely, there are MXML tags that do not have corresponding ActionScript classes and these (mx:Binding, mx:Component, mx:Style and more) are listed in the Flex Language Reference.

The Flex 2.0.1 Language Reference provides detailed information regarding MXML tags and their underlying ActionScript classes. The information included in each class/tag description includes the package the class/tag belongs to, the ancestry/inheritance tree for the class/tag, interfaces implemented by the class/tag, and subclasses of the class/tag.

Perhaps even more importantly, the language reference supplies the public and protected properties of the class/tag, the public and protected methods of the class/tag, the events that can be associated with the class/tag, the styles that can be applied to the class/tag, the effects that can be associated with the class/tag, and public constants provided by the class/tag.

When using an MXML tag, the specification of a property, event, effect, or style is typically almost trivial and often amounts to simply specifying an XML attribute on the MXML tag to specify the propery, event, effect, or style.

When using an ActionScript class equivalent of an MXML tag, some differences are introduced in terms of handling of properties, events, effects, and styles. However, ActionScript classes provide easy access to the methods associated with the class.

The following code example demonstrates using both MXML and direct ActionScript to accomplish the same thing. This example provides an easy way to contrast MXML syntax with ActionScript syntax.


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flash.display="flash.display.*"
width="500" height="300"
applicationComplete="compareThem();">

<mx:Resize id="enlargeButton"
widthTo="{BUTTON_WIDTH_LARGER}"
heightTo="{BUTTON_HEIGHT_LARGER}" />
<mx:Resize id="reduceButton"
widthTo="{BUTTON_WIDTH}"
heightTo="{BUTTON_HEIGHT}" />

<mx:Script>
<![CDATA[
/**
* To compile solely this Flex application from the command line, use
* mxmlc -strict=true Comparator.mxml
*
* This application demonstrates how MXML tags and direct ActionScript code
* handle specification of properties, events, effects, and styles.
*/

import mx.controls.Alert;
import mx.events.FlexEvent;

public const BUTTON_WIDTH:int = 250;
public const BUTTON_HEIGHT:int = 22;
public const BUTTON_WIDTH_LARGER:int = 400;
public const BUTTON_HEIGHT_LARGER:int = 75;

/**
* Compare MXML approach to ActionScript approach for designating properties,
* events, effects, and styles.
*
* Compare the examples to see how MXML and ActionScript handle some of these
* same designations differently. For example, in the Button constructed in
* both MXML and ActionScript, the following similarities and differences can
* be observed:
*
* <ul>
* <li>The "label" and "width" PROPERTIES are handled very similarly between
* the two approaches. Like everything else, MXML specifies properties
* with attributes on the XML tag. ActionScript assigns the property
* directly to the new value and typically takes advantage of underlying
* get / set accessor functions.</li>
* <li>The event handler for clicking down on the button is specified in the
* MXML tag as simply the buttonDown attribute with the value of that
* attribute set to the event handler method. In ActionScript, this same
* event handler method is associated with the button through the use of
* the method <code>addEventListener</code>.</li>
* <li>Styles are applied to components with <code>setStyle()</code> in
* ActionScript while they are specified in MXML via an attribute with
* the style name and the value of the attribute being the value to set
* that particular style to.</li>
* <li>Effects are applied to components in ActionScript in the exact same
* manner that styles are applied -- using the <code>setStyle</code>
* method. Likewise, effects are specified in MXML just as styles are
* specified in MXML -- using an attribute with the effect trigger name
* and supplying that attribute with the effect to occur.</li>
* </ul>
*/
private function compareThem():void
{
// The MXML button will be displayed as part of the normal application, so
// now call method to build second button with direct ActionScript.
generateAndApplyButton();
}

/**
* Construct a button with direct ActionScript and add it to main view box.
*/
private function generateAndApplyButton():void
{
const button:Button = new Button();
button.label = "Direct ActionScript Button"; // property
button.width = BUTTON_WIDTH; // property
button.addEventListener( FlexEvent.BUTTON_DOWN, // event
respondToButtonDown );
button.setStyle( "borderColor", "#0000FF" ); // style
button.setStyle( "color", "#FF0000" ); // style
button.setStyle( "rollOverEffect", enlargeButton ); // effect
button.setStyle( "rollOutEffect", reduceButton ); // effect
mainBox.addChild(button);
}

/**
* Event handler for button clicked down.
*
* @param aEvent Event associated with button down.
*/
private function respondToButtonDown(aEvent:Event):void
{
Alert.show("Thanks for clicking on the button!");
}
]]>
</mx:Script>

<mx:VBox id="mainBox">
<mx:Button id="mxmlButton"
label="MXML Button"
width="{BUTTON_WIDTH}"
buttonDown="respondToButtonDown(event)"
borderColor="#0000FF"
color="#FF0000"
rollOverEffect="enlargeButton"
rollOutEffect="reduceButton" />
</mx:VBox>

</mx:Application>



It is impossible to capture all of the event handling and effects handling in a single snapshot, but the image below (click on it to see it larger) shows some of them in action.



From the code comparison we can quickly ascertain some differences between MXML and direct ActionScript for handling of events, effects, and styles. Note that properties are handled very similarly for both coding approaches. However, there are cases where properties are handled a little more differently between MXML and ActionScript. A good example of a different handling situation is the UIComponent width property (which is inherited by Button in the example). While not shown in the above example, the width can be expressed as a percentage in MXML, but not in ActionScript, where a percentWidth property should be used instead. In the above example, the width was declared as an absolute width in terms of pixels and so could be declared in the same manner in both MXML and ActionScript.

The example above shows that even when using binding the approach to setting properties is similar across MXML and ActionScript. Note that the ActionScript property assignment approach typically takes advantage of ActionScript's get/set accessor functions.

Event handling is specified differently in ActionScript than in MXML. An event handler is specified in MXML as an attribute similar to how properties were specified in MXML (but with the specification of a method name with the implicit event parameter). In ActionScript, however, the addEventListener method is used instead. The results are the same, however.

The Flex documentation for Button shows the styles that can be applied to a Button. Two of the styles that are available that are set in this example are the "color" (of text) style and the "borderColor" style. As for properties and events in MXML, styles in MXML are simply specified by placing the appropriate style name as an attribute on the MXML tag and then setting that attribute's value to the value desired for that style. In ActionScript, the setStyle method must be called and the name of the style is passed to the method along with the value for the style.

It is fairly obvious from the API and the method name setStyle that this is the appropriate method to set style on a component in ActionScript. However, it is less obvious that the setStyle method is also the ActionScript method for setting effect handling. Again, MXML allows the effect to be set simply as an attribute with attribute name matching the effect triggers supported by the component and with attribute value being the effect to take place when the effect trigger occurs. The Button class inherits all of its effect handlers and even has some default effects applied without additional specification. For this example, two Resize effects are used. Interestingly, the effects applied in this example to enlarge and shrink the buttons on rollOver and rollOut respectively are applied on top of the effect changes that occur on the button by default.

Note that I listed resources for locating the standard Flex events in my last blog entry.

As the examples above and the analysis after the examples showed, MXML handles properties, events, styles, and effects in really the only way that it can -- as XML attributes because MXML is XML. ActionScript, on the other hand, sets properties directly using get/set accessor functions, sets events with addEventListener(), and sets styles and effects with setStyle().

There are several conveniences that can be enjoyed when using MXML tags that are not similarly enjoyed when using ActionScript directly. These include the ability to associate properties, styles, events, and effects with the MXML tag in essentially the same manner (as XML attributes for the XML tag) instead of different approaches for each as is necessary with ActionScript. Another advantage of MXML is that all Flex ActionScript classes are automatically visible to the application and no import statement is required. ActionScript requires non-global classes to be imported.

The conventional Flex wisdom is to use MXML for view and layout purposes and then to use ActionScript for business logic purposes. This corresponds roughly with the idea of using JavaServer Pages HTML/XML syntax for view with Java code for the business logic.

2 comments:

cubiclegrrl said...

FINALLY! Someone answers the basic question of when to use AS vs. MXML! Thank you so much!

At work, we'll more than likely migrating to Flash. I'm trying to get up to speed, just to keep pace with the rest of the pack, and my chief frustration is the mulligan stew of product-branding: Flash, Flex, Flex 2 SDK, ActionScript, MXML. But will anyone bother to explain to st00p1d n00b$ like me what the difference is, or even what I'm supposed to do with any of them? Apparently not. Too reminiscent of the dot-com alphabet soup technology days.

So thank you again for spelling out what Flash developers apparently just *know*, but the rest of us are left out in the dark to scratch our heads over.

@DustinMarx said...

Thanks for the nice feedback. It is satisfying to know when the time spent writing a blog has been of use to someone.

Thanks for letting me know it was helpful.

Dustin