Home > Development > blogs
Flex 4, states, and bad MXML
Ted Patrick has a post up on his blog about a new feature in Flex 4 that will allow for state-specific variables to be nested in individual components. Ted claims that in Flex 3 and below, States have been too hard to use and edit outside of the "design view" (someone uses the design view?), so an effort has been made to simplify them. The new code posted on Ted's blog looks something like this:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="library:ns.adobe.com/flex/halo"
xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<m:states>
<m:State name="landState"/>
<m:State name="airState"/>
<m:State name="waterState"/>
</m:states>
<mx:VBox id="vbox">
<mx:HBox>
<mx:Button id="land" label="Land" click="currentState='landState'" />
<mx:Button id="air" label="Air" click="currentState='airState'" />
<mx:Button id="water" label="Water" click="currentState='waterState'" />
</mx:HBox>
<mx:CheckBox label="Helicopter" color.airState="0xFF0000"/>
<mx:CheckBox label="Motorcycle" color.landState="0xFF0000" />
<mx:CheckBox label="Car" color.landState="0xFF0000" />
<mx:CheckBox label="Airplane" color.airState="0xFF0000"/>
<mx:CheckBox label="Train" color.landState="0xFF0000" />
<mx:CheckBox label="Boat" color.waterState="0xFF0000"/>
<mx:CheckBox label="Submarine" color.waterState="0xFF0000"/>
</mx:VBox>
</mx:Application>
I'm sure this will go fine, but as a person resistant to any language change that can create bad code, I'm worried about how many of these state-specific variables we're going to see. Imagine if one of his check boxes was written like this:
<mx:CheckBox id="changeWithState" color.waterState="0xFF0000" color.landState="0xF0F000" color.airState="0xFF0000" />
Now, this is no big deal, but if we add a few more states, it'd get unwieldy. And we really wouldn't want these colors hard-coded into the MXML, which means should be assigned on a model somewhere, so now the code looks like this:
<mx:CheckBox id="changeWithState" color.waterState="{Model.WATER_COLOR}" color.landState="{Model.LAND_COLOR}" color.airState="{Model.AIR_COLOR}" />
And this is probably even worse, because MXML doesn't distinguish between assigned data and bound data, so all of these colors are bound to the model whether we need it or not creating a slough of meaningless getter and setter methods that our compiler will have to sludge through.
In my opinion, a better way to assign these properties would be in ActionScript, where the code is more clear and no binding is required. All our MXML would bind to is a single model object, like this:
<mx:Model id="checkBoxStateModel">
<color>
<airState>0xff0000</airState>
<waterState>0x00ff00</waterState>
<landState>0x0000ff</landState>
</color>
</mx:Model>
<myCode:StatableCheckBox id="changeWithState" stateModel="{checkBoxStateModel}"/>
Then write your checkbox in actionscript to parse it's model, subscribe for a parents' stateChange events, and adjust it's properties accordingly. A base "statableObject" class could be written to handle the state-parsing and property-updating and be reused in multiple places.
I like this solution better for a number of reasons: it keeps our MXML cleaner, makes a cool reusable "statable" object, and allows us to externalize the state-specific data in a model object without adding lots of unnecessary binding to our code.
Have said all of that, I guess Ted's solution is still a huge improvement over the current slough of "addChild" / "removeChild" tags that states require.
Go check out the spec...there's a concept called "State Groups" that deals with large scale state targeting as well. e.g. color.MyStateGroup="0x000000" could target a 'group' of states for example , where MyStateGroup refers to a list (defined previously) of separate but similar states grouped under the moniker "MyStateGroup".
@Corey - Thanks. Being able to group states doesn't really address the concern I'm bringing up here, though it is nice. There are certainly draw-backs with the current system but at least all of the code is organized by state -- you don't have to parse the entire class to make changes to a single state.
Agreed, there are definitely pros and cons to be weighed.
The designers who have been using the inline syntax, have weighed in that they really like the fact that transient components (state-specific) can be placed at their natural location in the dom, and that at a glance, you can infer the nature of said component instance over the span of several states. The whole in-context authoring is a plus.
Totally a matter of perspective I think. But I'm sensitive to your concerns. Especially around binding. We're making a conscious effort as well to address additional short comings of the legacy approach.
One being, it is now much easier to express (efficiently) a component instance being present in say 3 of 7 states, without necessitating the use of hierarchical states (or loading up the base state and sprinkling RemoveChild tags everywhere else).
We've also addressed several long standing states and databinding related issues such as, when a databound state-specific value changes while in a state, the value now correctly updates (prior it would only be applied when the state changed as in your example above).
Keep the feedback coming, feel free to also chime in on the spec itself, or propose enhancements. ;o) Now is certainly the best time (the paint is still wet).
Are these state specific changes exposed as styles? I'd be concerned because instead of these colors being stored in a model as stated in the post, we try to keep style information in CSS as much as possible. Otherwise we'd have to move to the model approach so there would still be a central location to modify the styles.
Thanks Corey! For all of those who are interested, the spec is here.
Danny - even if they weren't exposed as styles to begin with you could expose your own styles and achieve the same result.
I'd expect a implementation of State-specific stylName. Thus you could have something like
DK
bugger...code chop!
Button styleName.air=...styleName.fire=....