Learning Flex – Lesson 6, Part II

E4X

E4X or ECMAScript for XML is ActionScript 3.0’s native support for XML. This allows easy access to XML for programmers . To show how to use E4X, we’re first going to need some sample XML:

<zoo>
<animals>
<animal name="leo">
<type>lion</type>
<sex>male</sex>
</animal>
<animal name="karen">
<type>kangaroo</type>
<sex>female</sex>
</animal>
<animal name="susan">
<type>snake</type>
<sex>female</sex>
</animal>
</animals>
<animal name="fred">
<type>fish</type>
<sex>male</sex>
</animal>
</zoo>

For this XML, the root node  is “zoo”, each animal has one attribute, “name” and two child nodes (also called child elements) “type” and “sex”.

When using E4X expressions, the root node is not used so to access the animal nodes, we would use the expression animals.animal this returns all the animal nodes that are the direct descendant of the animals node. In this case that would be leo, karen and susan NOT fred. To get only the first animal node, we would use animals.animal[0]

predicate filtering

We can use predicate filtering to return only data that satisfies the  provided conditions. For example, to get the animal named leo, we would use animals.animal.(@name=="leo") the @ symbol is used to indicate we’re using an attribute. To get the female animals, we would use animals.animal.(sex=="female") this would give us the data for karen and susan. You can apply predicate filtering multiple times to further restrict the result set.

descendant accessor

Remember how animals.animal only returns the direct children of animals? Using the descendant accessor “..” we can access all the descendants and return them wherever they are below our starting point.  Thus using ..animal we can return not only leo, karen and susan but fred too.

ArrayCollection sorting and cursors

To sort an ArrayCollection, we need to define a Sort object which contains an array of SortField objects. The SortField objects define the fields the ArrayCollection is to be sorted by (in order). The Sort object has a fields property to take this array. For only one field, we could define our sort as follows:

var mySort:Sort = new Sort();
mysort.fields=[new SortField("field name to sort by")];

There are three optional parameters for SortField objects:

  • case sensitivity (default false)
  • ascending or descending (default descending)
  • numeric or alphabetic (default is alphabetic)

Once we have our sort defined, we assign it to the the ArrayCollection’s sort property and then apply the sort by calling the refresh() method of the collection.

cursors

A cursor is a position indicator that allows direct access to any item in a collection. You can move a cursor forwards, backwards, find specific items and  retrieve, add or remove items at the cursor position.

Any class that implements the ICursorView interface can use cursors.

The steps to using a cursor are:

  • create the cursor using the collection’s createCursor() method
  • sort the collection
  • use cursor methods such as findFirst(), findLast(), findAny() to locate items in the collection
  • use cursor.current to address the item at the cursor position (must cast to the item type)

Note that findAny() may have a slight performance advantage.

Learning Flex-Lesson 6, Remote XML Data with Controls

Specifying a file as the source of a model might lead you to think that the file would be read in at runtime but you’d be wrong. The XML is actually compiled into the SWF.

Loading a file at runtime requires you to use the HTTPService class. To do this you need to:

  1. create an HTTPService object
  2. invoke it’s send method (often as part of the application creationComplete)
  3. handle the data returned

You create the object by (at a minimum) specifying an id and a url for the location of the data (either a web address or file system location). An example would be:

<mx:HTTPService id="myService" url="http://www.myserver.com/myFile.xml />

Flex is subject to the security constraints of FlashPlayer which means that and application loaded on domain 1 cannot load data from domain 2 unless domain 1 is specified in a crossdomain.xml file on domain 2. A file that would allow anyone access would look like:

<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>

The returned data can be handled in two different ways – either via data binding or using a result event handler.

When you use data binding, the result is stored in a variable named lastResult. To access part of the xml data you would use the following format – serviceID.lastResult.XMLRoot.XMLElement

To handle the data via an event, specify the event handler function for the result property in your HTTPService definition. You can also define an event handler for the fault property in case there’s a problem retrieving the data.

The result handler will require an event parameter of type ResultEvent and the data can be accessed using the format – event.result.XMLRoot.XMLElement

ArrayCollection

By default, complex data structures are returned as ArrayCollections. When an ArrayCollection used in a data binding changes, the visual component it is bound to is automatically updated. It is important to note that this is not the case if you use a regular array object.  The ArrayCollection class needs to be imported to be used in your application.

List based controls (such as list, tree, dataGrid etc) use a dataProvider property to bind to data which can be set to an ArrayCollection. When using a list, it’s important to specify the labelField property to tell the list what property of the ArrayCollection is to appear.

Items can be added to an ArrayCollection using either the addItemAt method and specifying the item and the position (zero based index) or addItem which will add the item to the end of the collection.