XML and the AvancedDataGrid, step two
In August, I posted a simple application that shows how the Flex 3 AdvancedDataGrid handles XML data. What I did not discuss in the accompanying blog entry is the fact that binding the XML from the server directly to a UI component is not generally the best design for a real-world application. Unless you’re building a very simple one-off application that is not likely to be significantly extended or modified, it is better to create collections of ActionScript objects to hold the data, and then bind these collections to the UI components.
This is a better design for a number of reasons. One reason is that it makes it easier to create multiple views of the same data. Another reason is that it makes the application more maintainable, because the server-facing code is isolated in specialized classes rather than being spread throughout your Flex code. And another reason is that it can make it easier to create and update data; it is often a simple matter of passing an instance of your ActionScript class to the server API.
OK, it is easy to say all that, but how do you actually do it? For starters, take a look at this sample application:
The application simply displays employee data grouped by role. The data comes from two separate server calls, one of which gets the list of roles, and the other the list of employees. The data from each call is stored in an ArrayCollection of custom ActionScript objects which I call Value Objects, or VOs, but are sometimes called Data Transfer Objects, or DTOs. Having these two collections of objects representing my data gives me a great deal of flexibility in the UI; I could do a lot of interesting things with data stored in this way. In order to show the data in the AdvancedDataGrid, I put it into a HierarchicalData instance, which is bound to the control.
That’s a lot to follow, so let’s take a step back and look at some of the code. We’ll start in the result() method of the RoleProxy class. This is where the XML data is used to create a collection of RoleVO instances:
Here the server values for the id and name of each role are passed to the RoleVO constructor in order to create an instance with those values. As you would expect, the RoleVO constructor assigns these values to the instance properties.
Another way of accomplishing essentially the same thing can be seen in the result() method of the EmployeeProxy class. Here, the entire XML element representing an employee is passed to the EmployeeVO constructor:
If you take a look at the EmployeeVO constructor, you will see that it assigns the values of the XML attributes and child elements to the EmployeeVO instance properties.
OK, now that we have our two collections of value objects, we are ready to do something useful with them. For an example of how to do this, let’s move from the model to the view.
In the view component we can manipulate the data as needed in order to present the visualization desired. In this case, we want to display the data hierarchically, with employees as children of their respective roles. In order to accomplish this we loop over our collections to create a single ArrayCollection of dynamic objects that hold arrays of EmployeeVO instances and are identified by the corresponding roles. This is done in the onInitialDataLoad() method of AdvancedDataGridXMLVO. In the following snippet, roles is the collection of RoleVO objects, empys is the collection of EmployeeVO instances, and ac is the new ArrayCollection instance that we’re building from the two:
for(var i:int = 0; i < roles.length; i++)
{
// One object per Role
obj = new Object;
obj.role = roles.getItemAt(i).roleName;
obj.roleId = roles.getItemAt(i).id;
// An array of Employees for each role
arr = [];
// Loop over the Employee collection
for(var j:int = 0; j < empys.length; j++)
{
// Check the employee’s role ID
if(empys.getItemAt(j).roleId == obj.roleId)
{
// Add the employee to our array
arr.push(empys.getItemAt(j));
}
}
// Assign the array to a property on our dynamic object
obj.employees = arr;
// Add the object to the ArrayCollection
ac.addItem(obj);
}
When we have the new ArrayCollection, we then use it to create our HierarchicalData instance:
// Let Flex know which field represents Child objects
employeeRoleData.childrenField = “employees”;
Because employeeRoleData is bound to the dataProvider property of our AdvancedDataGrid instance, the data is displayed automagically. In other words, we’re done!
As a side point, you’ll notice that the role names span several columns in order to provide a strong visual cue to indicate how the data is arranged. I got the idea from this post by Rob Rusher.
Now that we’ve seen how the application uses collections of value objects to provide a layer of abstraction between the view and the data, let’s take a higher-level look at how the application is architected. It does not use a framework such as PureMVC or Cairngorm, but the code is organized in a way that is similar to an MVC implementation. It is sort of an intermediary step between the brittle architectures that are typical of introductory Flex tutorials, and an extensible, maintainable, enterprise-class architecture:
If you walk through this flowchart (PDF), you can begin to see how the application is fairly easy to maintain. If I want to add a new visualization of the data, I just need to build a new view component that displays the existing ArrayCollections in a different way. If I want to change the source of my data, I just need to change the Proxy classes in the model - my view components don’t need to be touched.
Also, you can begin to see how this kind of architecture lends itself to team development. For example, if you have some developers who are very good with MXML and visualizations, you can have them focus on the view components, and they don’t have to know anything about the inner workings of the model classes. Similarly, you can have other developers build out the model without ever concerning themselves with the view components. This way neither group of developers ever gets in the other group’s way.
I architected the application this way because it seems to me that there aren’t many intermediary examples out there to help you make the leap from the very simple tutorial applications to applications built with full-blown frameworks. It occurs to me that this gap makes it difficult for many developers to appreciate the value of the frameworks. So, I offer this application as a way to help full in this gap. I hope to present some modifications to this application in future posts in order to highlight other aspects of good development practices, such as code reuse and encapsulation, so stay tuned.







Reader Comments
Great article and design. In dealing with more than two layers of hierarchy this method becomes much more challenging. I am in the midst of trying to develop a similar ADG but with a dynamic number of levels. Do you have any suggestions on the approach for doing this? Other examples I have viewed has the values of the XML doc in the attributes but this doesn’t seem like a sound solution. Any thoughts or suggestions?
@Rick,
Sorry for the delay in replying; I was hoping to create a new post with a sample application, but I have not found the time as yet. Meanwhile, to provide a short answer, let me suggest using something akin to the Composite pattern to address that issue.
Muy util.
Its great!
Muchas gracias
Thank you.