Flex tags and AS classes (continued)
In the previous post, I talked about how MXML tags map to ActionScript classes. I was planning on following that up with a short post about the exceptions to the earlier rules. However, a number of thoughtful comments helped me understand that there are more things that need explaining than just the original rules and the exceptions.
~
Instance variables and scoping
At the 50,000 foot level, all you need to know about MXML tags with ids is that they become variables. At the 10,000 foot level, you start caring what kind of variables these turn into.
Take, for example, the following block of code.
MyApp.mxml -- <Application> <HBox> <Image id="theImage" src="foo.gif" /> <Button id="theButton" label="hide image" click="theImage.visible = false" /> </HBox> </Application>
What kind of variable is theImage
? Well, it sort of feels like a global variable. After all, you access it without any qualifiers. But if you think about it a bit more, you will realize that true global variables would be visible anywhere in your program, no matter what file you were in. These variables are only visible from within this file, right?
As it turns out, each MXML file corresponds to a new ActionScript class, and the objects with ids on them turn into instance variables of that class. The above code is roughly equivalent to the following:
class MyApp extends Application { public var theImage : Image; public var theButton : Button; // In the real world, this initialization code is much // more complex and doesn't go in the constructor, // but you get the idea... public function MyApp() { var hbox = new HBox(); theImage = new Image(); theImage.src = foo.gif; hbox.addChild(theImage); theButton = new Button; theButton.label = "hide image"; theButton.addEventListener("click", temp1); hbox.addChild(theButton); this.addChild(hbox); } private function temp1(event: MouseEvent) : void { theImage.visible = false; } }
As you can see, theImage
and theButton
are member variables of the MyApp class. Note that it doesn’t matter where in the file these objects are defined. In this example, the image and button are inside of an hbox, but the variables are still defined on the outermost class, the application.
ActionScript inside MXML
Looking at the code example above, you will notice that event handlers are turned into functions. These functions are members of the outer class, and they have strongly typed signatures. In this case, an “event” parameter with the correct type is passed to the click handler. If you wanted to be perverse, you could even do things like define local variables within your inline event handler and it would all work just fine (although it is obviously not recommended).
What happens to ActionScript code inside of script blocks? Let’s take a look at the code below:
<Application> <Script> <![CDATA[ [Bindable] var foo : String; public function bar() : void { } ]]> </Script> </Application>
The code inside the script block is just inserted into the class definition, so this turns into:
class MyApp extends Application { [Bindable] var foo : String; public function bar() : void { } }
Any code you can put into the body of a class definition is valid in a Script block. This allows you to do things like attach metadata to getters and setters. And now that you know how the functions defined in MXML relate to the class, you now know how to access these methods from other objects. For example, if an MXML component defines functions like this:
PasswordEntry.mxml -- <VBox> <Script> public function get username() : String { return usernameField.text; } public function get password() : String; { return passwordField.text; } public function reset() : void { usernameField.text = passwordField.text = ""; } </Script> <HBox> <Label text="username" /> <TextInput id="usernameField" /> </HBox> <HBox> <Label text="password" /> <TextInput id="passwordField" /> </HBox> </VBox>
You can invoke them from another file like this:
<Application> <Script> public function foo() : void { Alert.show("username: " + pw.username + " password: " + pw.password); pw.reset(); } </Script> <PasswordEntry id="pw" /> <Button label="foo" click="foo()" /> </Application>
What’s next?
Ok, so I still need to write a post about the exceptions to the rules. And I think I should probably do one about different ways to separate your code from your design, including the technique of using inheritance between AS and MXML.
Please keep writing I’m passing these on to everyone I know who is working or planning on working in Flex. Great stuff.
Thanks for addressing the aspects we mentioned in the comments. I agree with Pablo; great stuff and please keep it coming.
Hi Sho,
Good stuff indeed.
In the “theImage” example above, people might think (if they didn’t read careful) that these member Variables are always on the application Class (as in the example), but when they would occur on another MXML file (a component), they would be member variables of that class.
cheers
Sho-
This is a great article, thanks. These features should greatly reduce the amount of burden on the ViewLocators…for example, updating a component on another screen. Before, I would retrieve the view helper and then call a getter, but now I can access the components directly.
You agree?
This is a really helpful post, thanks.
One thing that I still didn’t figure out is how to create component instances in MXML for classes with constructors that accept parameters.
[…] 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. […]
Excellent posts – thanks Sho.
[…] (Esta es la traducción del artÃculo “Flex tags and AS classes (continued)” de Kuwamoto.) […]
[…] and AS classes (continued)” de Kuwamoto.) tag this | permalink | trackback url Leave aComment […]
[…] (Esta es la traducción del artÃculo “Flex tags and AS classes (continued)” de Kuwamoto.) […]