Marc Hughes


Home
Blog
Twitter
LinkedIn
GitHub
about
I am a developer from a bit west of Boston.

Code in front

12 Mar 2007

I'm new to the whole Flex world. One of my first questions was to figure out how to link the components that I laid out in the mxml editor with the classes I created to control those components.

I googled around and found the way most people advocated to do it is with code behind. It consists of creating a base class in actionscript, then extending that class with mxml. This immediately struck me as an odd way of doing it, but I pushed on. It works pretty well.

But I've had this nagging feeling that it's doing things backwards. I have a component that I want to extend the functionality of through code. Why am I doing that inheritance in the opposite direction?

Trolltech makes a great development framework that I'm far more familiar with. They have a .ui format that generates c++ code in exactly the same way that flex has an .mxml format that generates actionscript code. But I think the Trolltech guys got it right just a little more than the Adobe guys. Their .ui generates the base class for you to extend.

So I put my "nagging feeling" and my experience with QT together and have come up with what I will call "Code in Front".

Code in Front Step 1
Create your component in mxml. Here's my example:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns="" xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label text="Hello World" id="mLabel"/>
<mx:Button label="Goodbye" id="mButton"/>
</mx:VBox>


Save this file as "TestComponentBase.mxml". This way, a class named "TestComponentBase" will automatically be generated during compile time. We're going to extend that class in the next step, hence the term: "code in front"

Code in Front Step 2
Create your actionscript class by extending the mxml class. Mine looks something like this:
package
{
import mx.events.FlexEvent;
import flash.events.MouseEvent;

public class TestComponent extends TestComponentBase
{
public function TestComponent()
{
super();
addEventListener(FlexEvent.CREATION_COMPLETE, init);
}

protected function init(event:FlexEvent) : void
{
mButton.addEventListener(MouseEvent.CLICK, onButtonClick );
}

protected function onButtonClick(event:MouseEvent) : void
{
mLabel.text = "Goodbye World!!!!";
}

}
}


Code behind step 3:
Use your new component in your application.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" xmlns:ns1="
" width="423" height="400">
<ns1:TestComponent />
<ns1:TestComponent />
<ns1:TestComponent />
</mx:Application>

And that's all there is to it. Easy, elegant, makes sense to me.

But there is one huge downfall to this. When using flex builder in design mode to lay out your controls in your app, this is all you see for the above mxml:



That's losing way too much of the functionality of the tools for most people and I agree. Luckily, there is a way to fix this. First, create a new project based on a Flex Library. Then, inside that project create a new directory from the flex ide. Call that directory "src" and click the "advanced" button. Link that directory to your source directory from your "main" project. You should see something like this:



From this newly created project, right click your component class (TestComponent.as in my example) and select "Include class in library". Assuming "Build Automatically" is checked off in your project menu, you will shortly get a brand new .swc inside your bin directory.

Now, go back to your "main" project. Right click the project, go to properties. Select "Flex build path" on the left. Select the "Library path" tab on the right. Click the "add swc" button and add that swc we just made in the above step.




Now, go back to your application mxml, go into design mode, click the refresh button, and bamn:



You can now edit the actionscript all you like without problems.

But now a new problem arises. If you edit the mxml base component, and then go back to your application mxml, those custom components are just blank boxes again. Relaunching flex builder fixes this. Going to the properties of your project (not changing anything) and clicking "ok" also fixes it. But that's a big inconvenience and is something worth investigating to fix.

I'm pretty sure I can replace the whole second-project thing with an ant build task and make that automatically build by installing ant into flex builder. That will most likely fix the problem.

For the record, I'm not claiming to have come up with some novel way of doing things. This idea is so obvious that it's very likely that someone somewhere else has had it before.