Cairngorm Getting Started Part Six – Displaying the Data

Now we’ve got the data back we need somewhere to store it.  This is where the model comes in.  Let’s create a ModelLocator called MemoryModelLocator.  It implements IModelLocator.  The interface doesn’t actually require any functions, it is just there to type the class.  Here’s the class

package com.worthyashes.simpleCairngorm.model
{
	import com.adobe.cairngorm.model.IModelLocator;
	[Bindable]
	public class MemoryModelLocator implements IModelLocator
	{
		//Singleton code
		private static var _instance:MemoryModelLocator;

		public function MemoryModelLocator(enforcer:SingletonEnforcer)
		{
			if (enforcer == null)
			{
				throw new Error("Like at the end of Highlander, before the crap sequal, there can be only one");
			}
		}

		public static function getInstance():MemoryModelLocator
		{
			if (_instance == null)
			{
				_instance = new MemoryModelLocator(new SingletonEnforcer());
			}
			return _instance;
		}
		//End of singleton code

		//Pop your vars into the model from here on
		public var loadedData:XMLList = new XMLList();
	}
}
class SingletonEnforcer{}

This is pretty much what we did in part two, the only addition being the variable loadedData which is of type XMLList.  Remember the most important thing is that this whole class is bindable.  This allows us to access the variables in this class using dynamic data binding.

Lets get the data in.  Back to our LoadXMLResponder class, remember Models in Cairngorm should ONLY be modified by a Command or a Responder.

package com.worthyashes.simpleCairngorm.responder
{
	import com.worthyashes.simpleCairngorm.model.MemoryModelLocator;

	import mx.rpc.IResponder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;

	public class LoadXMLResponder implements IResponder
	{
		public function LoadXMLResponder()
		{
		}

		public function result(data:Object):void
		{
			var resultEvent:ResultEvent = data as ResultEvent;
			trace("XML loaded");

			var memoryModel:MemoryModelLocator = MemoryModelLocator.getInstance();
			memoryModel.loadedData = resultEvent.result.block as XMLList;
		}

		public function fault(info:Object):void
		{
			var faultEvent:FaultEvent = info as FaultEvent;

			trace("Fault at [LoadXMLResponder] " + faultEvent.message);
		}

	}
}

Obviously we populate the data in the result function.  We create a local variable of the memoryModel, don’t forget that as a Singleton we can’t access it directly, we need to call the static getInstance() function on the class.  This ensures that we always get the same singleton back regardless of where we are in the application.  As we are using the e4x result format we can use dot notation to drill down the XML to return the XML <block> nodes as an XMLList.

So – great we’ve populated the Model.  Whoopy do.  Well whoopy do indeed, because we’ve got the data in a class that is the same at every point in the application and it’s bindable.

Look back at the main application file, currently we have a Tree component and a TextArea component.  Lets ignore the TextArea component for a mo and we’ll focus on the Tree.  I’m going to take the Tree and it’s holding Box out of this file and create it as a custom component in the view folder.

<?xml version="1.0" encoding="utf-8"?>
<mx:Box  xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
		<![CDATA[
			import com.worthyashes.simpleCairngorm.model.MemoryModelLocator;
			[Bindable]
			private var memoryModel:MemoryModelLocator = MemoryModelLocator.getInstance();

			private function renderLabel(item:Object):String
			{
				var node:XML = item as XML;

				if (node.localName() == "block")
				{
					return node.@title;
				}
				else if (node.localName() == "item")
				{
					return node.@name;
				}
				return "Something went wrong!!";
			}
		]]>
	</mx:Script>

	<mx:Tree dataProvider="{memoryModel.loadedData}"
			 width="100%"
			 height="100%"
			 labelFunction="renderLabel"/>
</mx:Box>

So what’s happening here?  What we are doing is creating an instance of the MemoryModelLocator class, and binding it to the tree as it’s data provider.  This means that when the LoadXMLResponder loads the XML and changes the property loadedData it updates the Tree component.  This is what we mean when we say the model updates the view.  The model doesn’t ‘know’ it has a view watching it, but when it changes regardless it updates the data being used by the views bound to it.  Pretty cool.  All we need to do now is render the label for the Tree and we are done!

Pop this into the main application file

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
				xmlns:view="com.worthyashes.simpleCairngorm.view.*"
				xmlns:control="com.worthyashes.simpleCairngorm.control.*"
				xmlns:business="com.worthyashes.simpleCairngorm.business.*"
				creationComplete="creationCompleteHandler();"
				layout="vertical">

	<mx:Script>
		<![CDATA[

			private function creationCompleteHandler():void
			{
				var loadXMLEvent:LoadXMLEvent = new LoadXMLEvent();
				loadXMLEvent.dispatch();
			}

		]]>
	</mx:Script>

	<control:SimpleFrontController id="frontController"/>

	<business:Services id="services"/>

	<mx:Panel title="XML Display" width="600" height="500">
		<mx:ViewStack width="100%" height="100%">
			<view:XMLTree id="xmlTree"/>
			<mx:Box>
            	<mx:TextArea/>
            </mx:Box>
		</mx:ViewStack>
		<mx:ControlBar>
			<mx:Button id="btn_tree" label="Display as Tree"/>
			<mx:Button id="btn_datagrid" label="Display as Datagrid"/>
		</mx:ControlBar>
	</mx:Panel>

</mx:Application>

We’ve again created an xmlns with the name of view to allow us to access the com.worthyashes.simpleCairngorm.view package.  So now when we run this we will display the XML in the tree.

Next let’s have a look at using a ModelLocator to manage state.

Tags »

Author:admin
Date: Thursday, 31. July 2008 10:24
Trackback: Trackback-URL Category: Cairngorm, Flex, Frameworks, Tutorials

Feed for the post RSS 2.0 Comment this post

Submit comment