In this post I’m continuing the theme of my last two posts, type-safe DataProviders, and combining it with the theme of the two posts before that: the Parsley application framework. I’ll be using Parsley’s DynamicCommand object to encapsulate the fetching of data from a server and then store it in a type-safe DataProvider that will be used with a DataGrid. If you haven’t read my previous two posts you’ll need to do that to get the most out of this post. I’d recommend starting with the first post of the pair, Type-Safe DataProviders for Flex Lists with the ActionScript Vector.
A Type-Safe DataProvider for the Flex DataGrid
My first theme, type-safety, addresses the fact that the built-in Flex types ArrayList and ArrayCollection, which are used as data providers for List & DataGrid controls, are not type-safe. So, if you intend to provide a list of Employees as the data source for your DataGrid you have no way to ensure that some other developer hasn’t accidentally passed you an ArrayList of Dogs, for example. (Well, you could iterate over the entire collection, checking the type of each element, before supplying it to your DataGrid. But who actually does that?) ActionScript does provide a type-safe collection class, Vector, but it doesn’t work as a List/DataGrid DataProvider.
This application wraps an instance of Vector.<Employee> in a class to provide type-safe access. This class implements IList so that the DataGrid can use it as a DataProvider. And, the app encapsulates retrieval of the data from the server in a ParsleyDynamicCommand. Right-click the app to view source or download an FXP file here.
My previous two posts demonstrated a technique with which you can use the Vector to gain type-safety while still providing the IList interface that Flex’s list & grid controls require. Since I’ve already covered that ground I won’t explain how that works here. In this example, the type-safe collection is called EmployeeDataProvider and it implements two interfaces, IList and IEmployeeDataProvider. The latter interface is the one which ensures type-safety:
public interface IEmployeeDataProvider { function pop():Employee; function push(value:Employee):uint; } |
Only Employee objects can be added to the collection through this interface. Here’s the beginning of the EmployeeDataProvider class:
public class EmployeeDataProvider extends EventDispatcher implements IList, IEmployeeDataProvider { private var _employees:Vector.<Employee> = new Vector.<Employee>; public function EmployeeDataProvider(target:IEventDispatcher=null) { super(target); } // // IEmployeeDataProvider // public function pop():Employee { var poppedEmployee:Employee = _employees.pop(); var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); event.kind = CollectionEventKind.REMOVE; event.items.push(poppedEmployee); event.location = _employees.length; dispatchEvent(event); return poppedEmployee; } public function push(value:Employee):uint { var count:uint = _employees.push(value); var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); event.kind = CollectionEventKind.ADD; event.items.push(value); event.location = count-1; dispatchEvent(event); return count; } |
By using the type-safe container, Vector, we ensure the type-safety of our container object, EmployeeDataProvider. The two functions, pop & push, mostly contain code for dispatching events so that the DataGrid can react to changes in the collection. Other than that, they delegate push & pop to the Flex Vector.
I’m not showing the code that implements IList here because I’ve explained it in my previous posts. (But you can View Source on the SWF above if you want to see it.) The IList interface is not used by my code. The IList implementation is provided only so that the DataGrid will be able to use EmployeeDataProvider as a data source.
Creating a Flex Data Service to Read XML
The data used in this example is a simple XML file that is hosted on my server at http://flexperiential.com/code/employees.xml. I created a Flex HTTPService to fetch this data by choosing Data –> Connect to Data Service from the Flash Builder menu:

After creating the service I right-clicked on the new getEmployees method in the Data/Services window and selected Configure Return Type. Flash Builder then automatically created value objects to match the data: Employee objects containing fields for firstname, lastname, title, email, etc.
Using Parsley DynamicCommand to Fetch Data from the Server
A common pattern for fetching server data is to encapsulate the web service in a command object. Parsley provides a convenient DynamicCommand object which is tailor-made for this purpose. Here’s my class that will be instantiated using DynamicCommand:
public class GetEmployeesCmd extends EventDispatcher { [Inject] public var employeeService:EmployeeServce; [Inject] public var employeeDataProvider:EmployeeDataProvider; public function GetEmployeesCmd() { } public function execute(event:EmployeeServiceEvent):AsyncToken { return employeeService.getEmployees(); } public function result(data:Object):void { for (var i:int = 0; i < data.employee.length; i++) { var employee:Employee = data.employee[i] as Employee; employeeDataProvider.push(employee); } } public function error (info:Object): void { trace("Error fetching employees"); } } |
This class contains three methods named so that Parsley will automatically recognize them and wire them up: execute, result and error. When you invoke the DynamicCommand Parsley automatically calls the execute method. And, Parsley automatically calls the result method when the service returns its data (ResultEvent) or, in case of an error (FaultEvent), the error method.
I’m also using Parsley here to inject instances of the EmployeeService and the EmployeeDataProvider.
Parsley Context/Configuration
Here’s the Parsley context file that ties all of this together:
<models:EmployeeDataProvider/> <employeeservce:EmployeeServce/> <spicefactory:DynamicCommand type="{GetEmployeesCmd}" selector="{EmployeeServiceEvent.LOAD_EMPLOYEES_REQUEST}"> <spicefactory:ManagedEvents names="{[EmployeeServiceEvent.LOAD_EMPLOYEES_REQUEST]}"/> </spicefactory:DynamicCommand> |
The first two lines specify that the EmployeeDataProvider and EmployeeService classes will be managed by Parsley. The type parameter shown in the DynamicCommand refers to the GetEmployeesCmd class discussed above. The names parameter specifies the event that will cause GetEmployeesCmd.execute to be invoked.
Application MXML File
The application file contains a couple of statements needed to complete the Parsley configuration:
<fx:Declarations> <parsley:ContextBuilder config="{ParsleyDynamicCommandContext}" /> <parsley:Configure /> </fx:Declarations> |
The first line specifies the context file name and the second line tells Parsley to configure the main app MXML file.
This init function is called after Parsley has finished its object injection and other work (this is specified by the [Init] meta tag):
[Init] public function init():void { dispatchEvent(new EmployeeServiceEvent(EmployeeServiceEvent.LOAD_EMPLOYEES_REQUEST)); } |
The function simply dispatches the event which causes the GetEmployeesCmd to be invoked. We also need to tell Parsley to manage the EmployeeServiceEvent event in the application file:
<fx:Metadata> [ManagedEvents("LoadEmployeesRequest")] </fx:Metadata> |
After the execute method has called the web service (just an XML file, here), the result method populates the EmployeeDataProvider instance which is shared by GetEmployeesCmd and the main application. It’s injected into the MXML application file like so:
[Bindable][Inject] public var employeeModel:EmployeeDataProvider; |
Finally, the app file contains a DataGrid which displays the employee data:
<mx:DataGrid dataProvider="{employeeModel}" height="100%" width="100%"> <mx:columns> <mx:DataGridColumn dataField="firstname" width="75" /> <mx:DataGridColumn dataField="lastname" width="75" /> <mx:DataGridColumn dataField="title" /> <mx:DataGridColumn dataField="email" /> <mx:DataGridColumn dataField="department" width="140" /> </mx:columns> </mx:DataGrid> |
Download the Flex project (fxp).
Next week I’ll finish this series of posts with a TypeSafeList abstract class that you can extend to quickly and easily build your own type-safe DataProviders.


{ 1 trackback }