20
Jul
09

Under the hood Flex data model using the fx:Model and fx:XML tags

When creating data model there are two popular ways to create data model in addition to VO / DTO. You can use the fx:Model and the fx:XML tags. These tags are mxmlc compiler tag. What it means is that the compiler handles these tags differently than the regular tags in MXML. In case you are like me and like to dig deep into how the mxmlc works than keep reading… In the Model or XML tags the source property can be set to an external source, however the compiler retrieve the information and set it as an ObjectProxy, which allow the object to be bindable, additionally it does direct assignment so there is no service call to retrieve the data as you may expect from an MXML tag. Consider the code below:


<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/halo"
			   minWidth="1024" minHeight="768"
                           creationComplete="creationCompleteHandler(event)">
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;

			protected function creationCompleteHandler(event:FlexEvent):void
			{
				trace("infoVO full name property: "+this.infoVO.fullName);
				trace("info2VO full name property: "+this.info2VO.fullName);
			}

		]]>
	</fx:Script>

	<fx:Declarations>

		<fx:Model id="infoVO">
			<root>
				<fullName>John Doe</fullName>
				<email>john@gmail.com</email>
				<phone>212-222-2222</phone>
				<zip>10001</zip>
			</root>
		</fx:Model>

		<fx:Model id="info2VO" source="Info.xml" />

	</fx:Declarations>

</s:Application>

We have two Model tags in the code and although one tag calls an xml using the source property and another one does direct assignment the mxmlc compile will generate the same code for both of these tags.

Take a look at what the compiler does when you use set infoVO and info2VO with the source property:


private function _DataModel_ObjectProxy2_i() : mx.utils.ObjectProxy
{
	var temp : mx.utils.ObjectProxy = new mx.utils.ObjectProxy();
	temp.fullName = "John Doe";
	temp.email = "john@gmail.com";
	temp.phone = "212-222-2222";
	temp.zip = 10001;
	info2VO = temp;
	return temp;
}

private function _DataModel_ObjectProxy1_i() : mx.utils.ObjectProxy
{
	var temp : mx.utils.ObjectProxy = new mx.utils.ObjectProxy();
	temp.fullName = "John Doe";
	temp.email = "john@gmail.com";
	temp.phone = "212-222-2222";
	temp.zip = 10001;
	infoVO = temp;
	return temp;
}

And here’s what the mxmlc code generated to create the binding tag:


    [Bindable(event="propertyChange")]
    public function get info2VO():mx.utils.ObjectProxy
    {
        return this._1945369341info2VO;
    }

    public function set info2VO(value:mx.utils.ObjectProxy):void
    {
    	var oldValue:Object = this._1945369341info2VO;
        if (oldValue !== value)
        {
            this._1945369341info2VO = value;
            this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this, "info2VO", oldValue, value));
        }
    }

	/**
	 * generated bindable wrapper for property infoVO (public)
	 * - generated setter
	 * - generated getter
	 * - original public var 'infoVO' moved to '_1184171033infoVO'
	 */

    [Bindable(event="propertyChange")]
    public function get infoVO():mx.utils.ObjectProxy
    {
        return this._1184171033infoVO;
    }

    public function set infoVO(value:mx.utils.ObjectProxy):void
    {
    	var oldValue:Object = this._1184171033infoVO;
        if (oldValue !== value)
        {
            this._1184171033infoVO = value;
            this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this, "infoVO", oldValue, value));
        }
    }

Since the mxmlc compiler create an ObjectProxy component it allows us to bind these properties as in the example below:


<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/halo"
			   minWidth="1024" minHeight="768">

	<s:layout>
		<s:BasicLayout/>
	</s:layout>

	<fx:Declarations>
		<fx:Model id="infoVO">
			<root>
				<fullName>{fullNameTextInput.text}</fullName>
				<email>{emailTextInput.text}</email>
				<phone>{phoneTextInput.text}</phone>
				<zip>{zipTextInput.text}</zip>
			</root>
		</fx:Model>
	</fx:Declarations>	

	<mx:DataGrid x="11" y="164" id="dataGrid"
				 dataProvider="{infoVO}">
		<mx:columns>
			<mx:DataGridColumn
				headerText="fullName"
				dataField="fullName"/>
			<mx:DataGridColumn
				headerText="email"
				dataField="email"/>
			<mx:DataGridColumn
				headerText="phone"
				dataField="phone"/>
			<mx:DataGridColumn
				headerText="zip"
				dataField="zip"/>
		</mx:columns>
	</mx:DataGrid>

	<mx:Form>
		<mx:FormItem label="FullName">
			<s:TextInput
				id="fullNameTextInput"/>
		</mx:FormItem>
		<mx:FormItem label="Email">
			<s:TextInput
				id="emailTextInput"/>
		</mx:FormItem>
		<mx:FormItem label="Phone">
			<s:TextInput
				id="phoneTextInput"/>
		</mx:FormItem>
		<mx:FormItem label="Zip">
			<s:TextInput
				id="zipTextInput"/>
		</mx:FormItem>
	</mx:Form>
</s:Application>

Here’s a screen shot of the application:
Flex Data Model

It valuable to understand how the mxmlc works and use these tags when needed.


5 Responses to “Under the hood Flex data model using the fx:Model and fx:XML tags”


  1. 1 Joel Lignier Aug 19th, 2009 at 7:22 am

    Hello and thanks for all the great information on this site. I’m still quite new to Flex development but am starting to really fall in love with this technology :)
    Currently, I’m in the planning stage for a new commercial application that is going to be developed using Flex and AIR. This application is going to be very database intensive and so I am exploring how flex data models can be used in conjunction with Sqlite. Do you have any thoughts on this topic or can you point me to any resources?

    Cheers.

  2. 2 elad.ny Aug 19th, 2009 at 11:02 am

    Hi Joel, if I understand what you are trying to achieve correctly, it sounds to me that you would need to create an architecture that keeps the state updated between the client, SQLite and Server.

    You can store the Web database locally and update when needed. I am working on an application that does that using LiveCycle. Here’s an API that can help you connect and perform SQLite tasks: http://elromdesign.com/blog/2009/04/16/adobe-air-sqlite-manager-api-for-adobe-air-15-with-password-encryption/. If this app is built from scratch you can match the server, client and SQLite so they are all using the same value objects structure.

  3. 3 Alfredo Duran Sep 10th, 2009 at 11:03 am

    I don’t know how to use but this example was great for me, Thank you

  4. 4 Jan Jan 14th, 2010 at 9:25 am

    Hey,

    I’ve got an other question, I’ve been using flash builder 4 for a week or 4, and it’s working really nice. But now i came to a problem, maybe it’s a binding issue..

    I’m using a java-backend with a flex frontend. And when i want to use a labelfunction it doesn’t load the indepth properties such as a value object, it’s like it is lazy loaded in the flex side, I’m sure it is not comming from the backend because i’ve checked it overthere.

    I’ve got it also in datagrid’s that it doesn’t load all the values at once.

    for example

    Class John{ var name:String; var lastName:Doe;

    }

    Class Doe{ var lastName:String; }

    I ask at my back end get all John’s, the backend gives me all John’s which contains the Doe’s. Now At the flex side I fire the result event from the callresponder when i receive that data. But still it can’t acces the doe’s into the Johns, the doe property of john is still null. When i ask it the second time it nows about the doe’s, so it looks like lazy loading in a front-end way…

    What am i doing wrong?

  1. 1 localToGlobal » Blog Archive » news review -> 30th week of 2009 Pingback on Jul 24th, 2009 at 10:01 am