4
Aug
2006

Flex tags and AS classes (the exceptions)

Here is the long overdue continuation of this topic. If you haven’t read the first two, you will probably want to at least skim this and this. Go ahead. I’ll wait.

Are you back? Good. Did the other two posts make sense? If not, you can stop reading, because this post is about the hairy details that those simple posts overlooked.

Still with me? Great! Now for the exceptions to the rules.

~

UIComponent is special

Exception 1 — Child tags of UIComponent are not handled through defaultProperty.

After reading the first two parts, you might be thinking to yourself: “I get it. UIComponent must have a property called children, and that’s how the child tags get added to UIComponent”. Good guess, but unfortunately, UIComponent is treated as a special case.

One reason is historical. Flex 1.0 and 1.5 didn’t have the concept of default property. There are other, real reasons why it would be hard to deal with the children of UIComponent in the same way as other tags. For starters, the initialization code for UIComponents is very complex. To get a sense of what it looks like, turn on the -keep flag on the compiler and look at the ActionScript code that is generated. Another reason is faceless components, which are not actually children of the UIComponent tag, which brings me to….

Faceless components are special

Exception 2 — Root tags of MXML files must inherit from UIComponent.
Exception 3 — Faceless components can only go at the root level of a document.

As far as I can tell, these two exceptions are here only for historical reasons. They are annoying to language purists, but they haven’t gotten in the way of people doing actual work, so we haven’t been able to justify the work it would take to make this consistent with the rest of the language. Let me explain.

A so-called faceless component is one that doesn’t derive from UIComponent. Some examples are the Parallel tag and the HTTPService tag, etc.

Anyway, the only way to create a faceless component is by subclassing an existing class using pure ActionScript. Usually, that’s ok. For example, you wouldn’t need MXML to create a subclass of HTTPService. There are a few times when it might make sense to use MXML to subclass an ActionScript class. For example, you might want to define a new effect class by putting a bunch of effects in parallel via MXML. Unfortunately, you can’t do that. This is the gist of exception 2.

<!-- This file will not compile -->
<mx:Parallel xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Fade alphaFrom="0" alphaTo="1"/>
    <mx:Move xBy="50" />
</mx:Parallel>

Exception 3 is about how faceless componets are used within MXML files. You can only put faceless components at the top level of an MXML file. There is no good reason for this, but then again, there is no good reason to put a faceless component anywhere other than the top level of your file.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:HBox >
        <!-- this won't compile -->
        <mx:HTTPService id="foo" />
    <mx:/HBox/>
</mx:Application >

Some tags are even more special

Exception 4 — Some tags don’t correspond to ActionScript classes and have special rules.

There are some tags which aren’t components at all (like the Script tag.. notice that there is no ActionScript class called Script) that are hard-coded into the compiler. The full list of these can be found here.

Unfortunately, each one has slightly different rules.

Allowed anywhere that UIComponent is allowed:

  • <Script> (surprising, but true)

Allowed only at the top level:

  • <Binding>
  • <Metadata>
  • <Model>
  • <Style>
  • <XML>
  • <XMLList>

Only allowed in factory properties (like itemRenderer)

  • <Component>

Only allowed inside of WebService:

  • <mx:operation>

Only allowed inside of RemoteObject:

  • <mx:method>

Only allowed inside of method:

  • <mx:arguments> (notice that this is the only case in the whole language where a lowercase tag is inside another lowercase tag!)

Only allowed inside of HTTPService and operation:

  • <mx:request>

There are other quirks, but in general, these rules don’t feel as awkward as they do when I write them down like this. You would never think to put an arguments tag in anything other than a method, and you wouldn’t put a method on anything other than RemoteObject.

Sometimes, you can use tags that don’t exist

Exception 5 — Certain tags, such as Model and XML allow you to enter any tag you want inside them.

The exception above is pretty self-explanatory. It is what it is.

Parting thoughts

You probably won’t need to know any of these above exceptions to do your work on an ongoing basis, but sometimes it helps to understand the minute details behind the technology you use. Hope you found it interesting!

15 Responses to “Flex tags and AS classes (the exceptions)”

  1. sven

    “Root tags of MXML files must inherit from UIComponent.”

    It’s a pity, because it means, that you have to use the flex framework in order to use mxml. It would be great to be able to use mxml only with my own classes.

  2. Dreamer

    Thank you !!!

    good post,as usual.

  3. Manish Jethani

    SoundPlayer is an example of a third-party faceless component.

  4. Rostislav Siryk

    >> Exception 2 — Root tags of MXML files must inherit from UIComponent.
    I guess this relates to impossibility to do something like HBox.addChild(Sprite). Am I right? Only descendants of UIComponent (Canvas for example) can be addChilded to MXML creatures, otherwise we get a “Type coercion error”, well seen in debugger player mode.
    Maybe this restriction is very simple to understood intuitively. However, I’ve spent some time to add Sprite as a child of different MXML components directly. Later, I’ve found through docs that only types that implement IUIComponent (or inherit from UIComponent, read below) can be added to MXML containers as child. This is because all visual MXML containers inherit from Container class whose addChild method overrides DisplayObjectContainer’s addChild method and adds a new requirement: it’s arguments must implements the IUIComponent interface.
    So, we can call DisplayObject class as the ‘base visual class’ of ‘pure AS3 work flow’, because this is the lowest-level acceptable type of original addChild(child: DisplayObject) signature (but situation changes in Flex project where MXML is the basement).
    Therefore, UIComponent is the ‘base visual class’ of ‘MXML (Flex Project) work flow’ because it’s the lowest-level acceptable type of the overrided addChild method. In other words: because UIComponent implements the IUIComponent, the easiest way to make addChild-bridge between your custom visual AS3 class and (built-in) visual Flex containers is to inherit your class from UIComponent. (For the sake of completeness, let’s say that UITextField is the second class which implements directly IUIComponent interface).
    I think this distinction is logical: you select your work flow/namespace and build your app using corresponding rules (and maybe it takes some time to understood this).

  5. sho

    Rostislav: I think you have gotten it right. However, you can add DisplayObjects to MXML objects if you are very careful by doing myHBox.rawchildren.addChild(sprite).

    Sven: We’ve heard this a few times before, and we’re considering how hard it would be to allow this. Thanks for the feedback.

  6. Rostislav Siryk

    Sho, thank you for very useful Flex insider info. Actually, I’ve been waiting until you finish this interesting cycle of posts to start my translating them into Russian as solid article about relationship between MXML and AS3 (if you don’t mind). Of course, with links to corresponding posts on your blog.

  7. sho

    Sure. Feel free to translate into Russian. Thanks for asking.

  8. Dreamer

    Hi,Sho:

    I am a chinese.I want to translate your posts into Chinese and publish on the web. I want more people in China to know and learn Flex. It is cool, isn’t it? Of course, all the translations will link to the original posts in your blog.

    Thanks very much

  9. sho

    That sounds fine, Dreamer. Thanks for asking.

  10. Mario Romero

    Hey Sho, those articles cleared some stuff up, however… I was having some trouble related to the topic, and maybe you could help out. I’m adding a TextField to a Panel (in actionscript), I’m using Flex2 and was getting the above mentioned type error.

    This is what I tried:

    public function putText() : void
    {
    var ref : UIComponent = new UIComponent();
    var field : TextField = new TextField();

    field = “a very long text goes here… “;
    ref.addChild( field );
    somePanel.addChild( ref );

    }

    This works in a way, but not so well because the text is just drawn over the panel and if it is to long, for example, it wont force the panel to scroll. I think it is similar to what happens with the addrawchild method, isn’t it??.

    what I want to do is render a big chunk of text on top of a panel, the text content I get from an xml file (with url loader)…

    let’s assume I now have a XML variable (externalXML) with my data.. then…

    for each ( var element:XML in externalXML.elements() ) {

    field.htmlText += ” ” + element.Name.toString() + “ “;

    }

    NOW… what would be the correct form to display “field” inside a Panel somewhere on my aplication?? the UIComponent gives me the above mentioned problem, adding the textField directly to the panel is a no go obviusly because of the type error…

    any help is appreciated,
    mario romero

  11. mituan

    Thank ! I try it!

  12. Hans

    I’m a new flexer,I met a strange problem.
    When I add a instance of a UIComponent based class into the MXML application,the Button on the instance was not displayed,the Button is a child on the UIComponent based class,and there is no debug error happened.
    If I change the base class to Canvas,the Button was displayed normally.
    Anyone can tell me a reason?

  13. Sly

    Surprisingly I found that I was not allowed a “mx:Script” as first child of a “mx:Component” inside a “mx:DataGrid”.

    I know DataGrids have many more secret rules and exceptions and many things must be broken in their implementation.

    Still, great post and thanks a lot !

  14. Justin Buser

    Sven: First of all, that’s not actually true. I think the author of this article is a bit confused. For instance, create an mxml file called TestObject.mxml in the main source folder for your application that contains the following:

    Test String 1

    Next in your application try the following:

    Results:

    When you run/debug the application you should see both test variables in the console window. Object is a Top Level Class, and doesn’t meet the requirements of UIComponent.

    Secondly, why would you ever want to use mxml for anything outside of flex’s framework? I don’t understand how you could have gotten to the point where you would need to do this without already knowing that AS3 based components/classes are vastly superior in every way. Were you just trying to sound smart or have you not learned Actionscript?

    Sho: Who the hell are you/we and what do you mean by “considering how hard it would be to allow this”? You obviously have nothing to do with Flex Builder/MXML/AS3 development or you would have immediately known that
    a.) The poster was simply wrong and Sven didn’t bother to actually try to do what he claims he wants to do.
    b.) Rostilav most likely suffers from some sort of congenital retardation, half of what he wrote is nonsensical gibberish. I mean seriously, “MXML creatures”,”‘base visual class’ of ‘pure AS3 work flow’”,”MXML is the basement”, who did he learn programming from, M. Night Shyamalan? It’s like he took a huge nitrous hit and just started typing whatever random crap came out of his head.

    So if you have no idea what you are talking about(this much is obvious) and have no influence over what is “allowed” why are you responding to idiotic drivel thereby perpetuating a useless discussion based on an imaginary problem and causing me to end up on this stupid blog reading things that just make my brain hurt? Please don’t do this anymore, at least until google somehow comes up with a way to differentiate between mental masturbation and actual useful content, or at least can tell the difference between real problems and those that only exist in the minds of clueless people who just like to see their names on blogs.

  15. Electrolux servisi

    Surprisingly I found that I was not allowed a “mx:Script” as first child of a “mx:Component” inside a “mx:DataGrid”.

Leave a Reply