Loading...

Thursday, January 28, 2010

Flex Basics - Local Shared Object

From Wikipedia, a browser cookie is a "small piece of text stored on a user's computer by a web browser. A cookie consists of one or more name-value pairs containing bits of information".

A web application uses cookies for session management, personalization and tracking. Most browsers restrict the size of a cookie to 4 kb.

In a Flex application, storing data on a user's computer for later use is accomplished using Local Shared Objects rather than cookies. A Local Shared Object can store up to 100 kb of data without asking permission of the user. Unlike cookies that are capable of storing only text values, Local Shared Objects can store many data types including Number, String, Boolean, XML, Date, Array & Object. Instances of a custom class can also be stored in a Local Shared Object when the custom class is registered using the [RemoteClass] metadata tag.

Create / retrieve a Local Shared Object

The process for creating a new Local Shared Object or retrieving an existing Local Shared Object is identical. In both cases, the static method getLocal() is used.

public static function getLocal(name:String, localPath:String = null, secure:Boolean = false):SharedObject

First, perform a call to the static method getLocal() of the SharedObject class, and then save the reference in a variable.

var myNewLocalSharedObject:SharedObject = SharedObject.getLocal("myNewLocalSharedObject");

Flash Player will look in a local directory on the user's computer for a Local Shared Object named myNewLocalSharedObject. More specifically, it will look in a directory unique to the SWF's domain for a file named myNewLocalSharedObject.sol. If myNewLocalSharedObject.sol is found, a reference to the existing Local Shared Object is returned. Otherwise, myNewLocalSharedObject.sol is created and a reference is returned to the newly created Local Shared Object.

To determine whether a new or existing Local Shared Object was returned, query the size property.

var myNewLocalSharedObject:SharedObject = SharedObject.getLocal("myNewLocalSharedObject");

if (myNewLocalSharedObject.size > 0)
{
    trace("Existing Local Shared Object");
}
else
{
    trace("New Local Shared Object");
}
The getLocal() method has three parameters. They should be used as follows:
  • The name parameter is required to assign a name to the Local Shared Object.

  • The localPath parameter is optional and should be used if you anticipate multiple SWF files from the SAME domain needing access to one Local Shared Object, or if the SWF file responsible for creating the Local Shared Object may be moved to another location within the SAME domain.

  • The secure parameter is optional and is used to create a secure Local Shared Object. Once created, any subsequent calls to the secure Local Shared Object must be made by a SWF delivered over HTTPS.

Access / update a Local Shared Object

A Local Shared Object may have many attributes. For example, customer data may include name, age, address and order IDs. Each of these attributes is represented by a property of the Local Shared Object's data property. These values can be accessed, updated or deleted.

// retrieve a reference to the existing Local Shared Object (customerData.sol)
var so:SharedObject = SharedObject.getLocal("customerData");

// accessing the values of the Local Shared Object
var name:String = so.data.name;
var age:int = so.data.age;

// updating the values of the Local Shared Object
so.data.name= "John Smith";
so.data.age = 23;
so.data.orderIds = [234562444425432];

// a custom class must be registered and marked serializable using the [RemoteClass] metadata tag
var address:Address = new Address();
address.street = "125 Foo Lane";
so.data.address = address;

// deleting values of the Local Shared Object
delete so.data.age;
delete so.data.orderIds;

Persist a Local Shared Object

Use the flush() method to immediately write a Local Shared Object to the user's computer.

public function flush(minDiskSpace:int = 0):String

A call to flush() returns one of two possible values, SharedObjectFlushStatus.PENDING or SharedObjectFlushStatus.FLUSHED. If more space is needed on the user's computer to persist the Local Shared Object, SharedObjectFlushStatus.PENDING is returned and a dialog box is presented to the user to obtain permission to allocate more space.



When the user selects "Allow" or "Deny" a NetStatusEvent.NET_STATUS event is dispatched targeting the Local Shared Object. Register an event listener to handle this event.

so.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
If the Local Shared Object is successfully written to the user's computer, SharedObjectFlushStatus.FLUSHED is returned and the user is not notified.

The flush() method has one parameter. It should be used as follows:
  • The minDiskSpace parameter is optional and is used to allocate additional space (over 100 kb) on the user's computer for the Local Shared Object. If used, a dialog box is presented to the user asking for permission to allocate additional space.

private function writeSharedObject():void
{
    var so:SharedObject = SharedObject.getLocal("mySO");
    so.data.name = "Jeremy Mitchell";
    try
    {
        // wrap in a try to handle a scenario where local storage has been disallowed
        so.flush(500000);
    }
    catch (e:Error)
    {
        trace("Local storage has been disabled for this domain");
    }
}
Note: The flush() method is not required to persist a Local Shared Object. When the application SWF closes, an attempt is made to persist all Local Shared Objects on the user's computer. However, if adequate space is not allocated for the Local Shared Object, the attempt will fail silently. Use the flush() method to ensure success and recover from any possible failure.

Delete a Local Shared Object

To purge the data of a Local Shared Object and delete it from the user's computer call the clear() method.

public function clear():void
var so:SharedObject = SharedObject.getLocal("loginInfo");
so.clear();

Labels: ,

Monday, December 7, 2009

Flex Basics - Creating a Popup Window with PopUpManager

Popup windows serve as a handy tool for data collection or display. Popup windows in Flex are frequently implemented as a TitleWindow or a subclass of TitleWindow. TitleWindow is a popular choice as it inherits the capabilities of a Panel (title bar, control bar, border & content area) while adding a nifty close button.



With built-in modal support, popup windows can demand the user's attention or force interaction when necessary. This is possible because windows below a modal popup window cannot receive mouse events until a modal popup window is dismissed.

The PopUpManager class is used to manage popup windows in Flex. You can create, center and remove popup windows by using the static methods of the PopUpManager class.

addPopUp()

public static function addPopUp(window:IFlexDisplayObject, parent:DisplayObject, modal:Boolean = false, childList:String = null):void
createPopUp()

public static function createPopUp(parent:DisplayObject, className:Class, modal:Boolean = false, childList:String = null):IFlexDisplayObject
centerPopUp()

public static function centerPopUp(popUp:IFlexDisplayObject):void
removePopUp()

public static function removePopUp(popUp:IFlexDisplayObject):void

Creating a popup window

Flex provides two distinct, yet very similar, methods for creating a popup window and placing it on a layer above all other visible windows – addPopUp() and createPopUp(). The difference between each method is subtle and determining which to use is mostly a matter of preference.

Note: Adobe documentation states that "using the addPopUp() method may be preferable to using the createPopUp() method if you have to pop up a simple dialog box that is never used elsewhere."
Looking closely at each method signature (addPopUp & createPopUp), the difference dictates how to use the method rather than when to use it. (or so it seems)

Method characteristicaddPopUp()createPopUp()
Requires a popup window instance as an argumentYesNo
Returns a value that can be stored in a variableNoYes

Here are some guidelines I tend to follow:

If you want to create a quick and dirty simple popup window that you don't plan to reuse, use addPopUp().
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="openTitleWindow(event)" >

    <mx:Script>
        <![CDATA[
            import mx.events.CloseEvent;
            import mx.controls.Label;
            import mx.events.FlexEvent;
            import mx.containers.TitleWindow;
            import mx.managers.PopUpManager;

            // method to open the TitleWindow on creationComplete
            private function openTitleWindow(evt:FlexEvent):void {
                // create and configure the TitleWindow
                var tw:TitleWindow = new TitleWindow();
                tw.title = "Title Goes Here";
                tw.showCloseButton = true;
                tw.addEventListener(Event.CLOSE, closeTitleWindow);
                // create and configure a Label
                var label:Label = new Label();
                label.text = "This is a very simple popup window";
                // add the Label to the TitleWindow
                tw.addChild(label);
                // open the TitleWindow as a modal popup window
                PopUpManager.addPopUp(tw, thistrue);
            }
            
            // method to close the TitleWindow targeted by a close event
            private function closeTitleWindow(evt:CloseEvent):void {
                PopUpManager.removePopUp(TitleWindow(evt.target));
            }
        ]]>
    </mx:Script>
    
</mx:Application>
If reuse of a popup window is a priority, use createPopUp() and store the returned object in a variable for later use.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="openPopUpWindow(event)" >

    <mx:Script>
        <![CDATA[
            import comps.MyPopUpWindow;
            import mx.events.FlexEvent;
            import mx.managers.PopUpManager;
            
            // declare a variable for the reusable custom PopUp Window
            private var popup:MyPopUpWindow;

            // method to open the PopUp Window on creationComplete
            private function openPopUpWindow(evt:FlexEvent):void {
                // open the PopUp Window as a modal popup window
                // and store it in a variable for later use
                popup = PopUpManager.createPopUp(this,MyPopUpWindow,trueas MyPopUpWindow;
            }
        ]]>
    </mx:Script>
    
</mx:Application>
<?xml version="1.0" encoding="utf-8"?>
<!-- custom popup window component - comps/MyPopUpWindow.mxml -->
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" 
        layout="vertical" 
        title="My Custom PopUp Window"
        showCloseButton="true">
         
        <mx:Form>
        
            <mx:FormHeading label="User Login"/>
            
            <mx:FormItem label="Username">
                <mx:TextInput id="un"/>
            </mx:FormItem>
            
            <mx:FormItem label="Password">
                <mx:TextInput id="pd"/>
            </mx:FormItem>
            
            <mx:ControlBar>
                <mx:Button id="save" label="Login"/>
                <mx:Button id="cancel" label="Cancel"/>
            </mx:ControlBar>
             
        </mx:Form>
        
</mx:TitleWindow>

Centering a popup window

A popup window can be centered in relation to any DisplayObject. When creating a popup window using addPopUp() or createPopUp(), it is important to understand that the parameter named "parent" (datatyped as DisplayObject) will be used to determine the reference point for centering a popup window. In most cases, you’ll want a popup window to be centered over the Application.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="openPopUpWindow(event)" >

    <mx:Script>
        <![CDATA[
            import comps.MyPopUpWindow;
            import mx.events.FlexEvent;
            import mx.managers.PopUpManager;
            
            // declare a variable for the reusable custom PopUp Window
            private var popup:MyPopUpWindow;

            // method to open the PopUp Window on creationComplete
            private function openPopUpWindow(evt:FlexEvent):void {
                // open the PopUp Window as a modal popup window
                // and store it in a variable for later use
                popup = PopUpManager.createPopUp(this,MyPopUpWindow,trueas MyPopUpWindow;
                // center the PopUp window
                PopUpManager.centerPopUp(popup);
            }
        ]]>
    </mx:Script>
    
</mx:Application>

In the previous example, notice that the DisplayObject used to center the popup window was this. In this case, this refers to the Application container, and therefore, the popup window was centered nicely over the Application. In many cases this will not refer to the Application container (i.e. inside custom components). When opening a popup window from within a custom component, use the following code to ensure the popup window is centered over the Application container and not the custom component.

popup = 
PopUpManager.createPopUp
(DisplayObject(this.parentApplication),MyPopUpWindow,trueas MyPopUpWindow;

Removing a popup window

Once our popup window has been created, displayed and optionally centered, there are a couple of options for removing it from display.

1. A parent removes a popup window from display

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="openPopUpWindow(event)">

    <mx:Script>
        <![CDATA[
            import mx.events.FlexMouseEvent;
            import comps.MyPopUpWindow;
            import mx.events.FlexEvent;
            import mx.managers.PopUpManager;
            
            // declare a variable for the reusable custom popup window
            private var popup:MyPopUpWindow;

            // method to open the popup window on creationComplete
            private function openPopUpWindow(evt:FlexEvent):void {
                // open the popup window as a modal popup window
                // and store it in a variable for later use
                popup = PopUpManager.createPopUp(this,MyPopUpWindow,trueas MyPopUpWindow;
                // register event listeners for closing the popup window
                // when the popup window close button is clicked...
                popup.addEventListener(Event.CLOSE, closePopUpWindow);
                // or when an area outside the popup window is clicked...
                popup.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, closePopUpWindow);
                // center the popup window
                PopUpManager.centerPopUp(popup);
            }
            
            // method to close the popup window on close or mousedownoutside event
            private function closePopUpWindow(evt:Event):void {
                PopUpManager.removePopUp(popup);
            }
        ]]>
    </mx:Script>
    
</mx:Application>

2. A popup window removes itself from display

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="openPopUpWindow(event)">

    <mx:Script>
        <![CDATA[
            import mx.events.FlexMouseEvent;
            import comps.MyPopUpWindow;
            import mx.events.FlexEvent;
            import mx.managers.PopUpManager;
            
            // declare a variable for the reusable custom popup window
            private var popup:MyPopUpWindow;

            // method to open the popup window on creationComplete
            private function openPopUpWindow(evt:FlexEvent):void {
                // open the popup window as a modal popup window
                // and store it in a variable for later use
                popup = PopUpManager.createPopUp(this,MyPopUpWindow,trueas MyPopUpWindow;
                // center the popup window
                PopUpManager.centerPopUp(popup);
            }
        ]]>
    </mx:Script>
    
</mx:Application>
<?xml version="1.0" encoding="utf-8"?>
<!-- custom popup window component - comps/MyPopUpWindow.mxml -->
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" 
        layout="vertical" 
        title="My Custom PopUp Window"
        showCloseButton="true"
        close="PopUpManager.removePopUp(this)">
        
        <mx:Script>
            <![CDATA[
                import mx.managers.PopUpManager;
            ]]>
        </mx:Script>
         
        <mx:Form>
        
            <mx:FormHeading label="User Login"/>
            
            <mx:FormItem label="Username">
                <mx:TextInput id="un"/>
            </mx:FormItem>
            
            <mx:FormItem label="Password">
                <mx:TextInput id="pd"/>
            </mx:FormItem>
            
            <mx:ControlBar>
                <mx:Button id="save" label="Login"/>
                <mx:Button id="cancel" label="Cancel"/>
            </mx:ControlBar>
             
        </mx:Form>
        
</mx:TitleWindow>

I hope that gives you some ideas about how to use PopUpManager & TitleWindow in your Flex apps. Have fun!

Labels: , ,

Friday, May 22, 2009

Flex Basics - XMLListCollection

Depending on the characteristics of a data set, data can be modeled in a linear or hierarchical fashion.

Linear data (aka flat or list-based data) typically represents the attributes (or properties) of an individual entity (item).

In turn, multiple items can be aggregated into a list and stored in an Array. An Array provides a mechanism for storage, manipulation and retrieval of linear data within a Flex application.



Note: Arrays can also store hierarchical data (i.e. objects composed of other objects or simple xml objects) but you'll find linear data to be more common.
Other data sets represent nested levels of information (hierarchical data). ActionScript provides two native datatypes for working with hierarchical data – XML and XMLList. The contents of each can be accessed and manipulated as needed utilizing the public API (properties and methods) corresponding to the supporting ActionScript class – XML or XMLList.

XML was designed to support the transport, storage and description of hierarchical data using custom markup. The XML class contains methods and properties for working with a single, well-formed XML document.

As one might guess, an XMLList is simply a list of XML objects. Looking closely at the methods of the XML class, you’ll notice that many operations potentially result in a match against multiple XML nodes (i.e. attributes(), children(), descendants(), etc). With each matching node representing the format of a well-formed XML document, it makes sense to provide a class designed to hold one or more XML objects. That class is the XMLList class.

Note: XML and XMLList classes support E4X operations that may also return a list of XML objects (XMLList). This includes shorthand operations such as (.) or (..) used for retrieving children or descendant nodes respectively or predicate filtering.
As a Flex developer, your intent, most likely, is to eventually render some, if not all, of your data on the screen. Whether your data is linear or hierarchical in nature, Flex provides the following “data provider” components suited for the task at hand:Data provider components require a reference to the data for display. This reference is captured in the dataProvider property of the data provider component instance.

<!-- MXML -->

<List id=”myList” dataProvider=”{myArray}” />
<Tree id=”myTree” dataProvider=”{myXMLList}” />

// ActionScript

var myList:List = new List();
myList.dataProvider = myArray;

var myTree:Tree = new Tree();
myTree.dataProvider = myXMLList;
At first glance, this appears to be an acceptable use of data binding. However, using raw data objects (Array, XML and XMLList) as a data provider for a UI control is not considered a best practice.

Instead, it is recommended that collections are used in place of raw data objects for the following reasons:
  • Changes to the data stored in a collection are immediately reflected in the UI control
  • Collections provide a "view" of the underlying data that can be sorted or filtered
Therefore, an ArrayCollection should be used in place of an Array (see related blog entry) and an XMLListCollection should stand in for an XMLList object.

XMLListCollection

Similar to an ArrayCollection, XMLListCollection extends the ListCollectionView class which implements the ICollectionView and IList interfaces. 3 members of the ICollectionView interface play an integral role in the implementing class' ability to support data binding:
  • 2 methods: addEventListener() & dispatchEvent()
  • 1 event: collectionChange
When the [Bindable] metadata tag is used with a collection, Flex generates code behind the scenes required to make the collection "bindable". This code is dependent on the ability to register an event handler triggered by a event dispatched when the data object changes (aka event listener). By extending ListCollectionView which implements ICollectionView, XMLListCollection becomes an eligible participant in the data binding game.

For a more detailed look at the guts of data binding, check out Michael Labriola's presentation entitled Diving in the Data Binding Waters

To create an XMLListCollection, 3 techniques are available:

// creating an empty XMLListCollection
private var myXMLListCollection:XMLListCollection = new XMLListCollection();

// passing an existing XMLList into an XMLListCollection via the constructor
private var myXMLListCollection:XMLListCollection = new XMLListCollection(myXMLList);

// assigning an existing XMLList to the source property of an XMLListCollection
private var myXMLListCollection:XMLListCollection = new XMLListCollection();
myXMLListCollection.source = myXMLList;
After being "wrapped" by an XMLListCollection, the majority of the XMLList methods are still available including (but not limited to):

- attributes
- child
- children
- copy
- descendants
- elements

Note: E4X shorthand operations also apply to an XMLListCollection
But now your plain old hierarchical data storage container (XMLList) has been infused with new powers including data binding (as mentioned previously) and new properties / methods.

New properties:

- filterfunction
- sort

New methods:

- addAll
- addAllAt
- addEventListener
- addItem
- addItemAt
- getItemAt
- getItemIndex
- refresh (for use with filterfunction and sort properties)

Note: These are the same properties and methods employed by an ArrayCollection. Sharing the same super class (ListViewCollection), ArrayCollection and XMLListCollection behave in a very similar manner, however, it is typically the UI control that will dictate the type of collection required as a data provider. Remember, list-based UI controls (DataGrid, List, TileList and HorizontalList) require linear (or flat) data structures (ArrayCollection) while tree or menu-based controls (Tree, Menu, MenuBar, PopUpMenuButton) require hierarchical data structures (XMLListCollection).

In addition to the enhanced API provided by a collection, wrapping an XMLList inside an XMLListCollection provides 2 very powerful features:
  1. filtering
  2. sorting
A collection provides a "view" of the underlying data (Array or XMLList) that can be filtered and sorted without affecting the underlying data. It is this "view" in which UI controls are bound to. Alter the "view" using the filterfunction or sort properties along with the refresh() method and the changes are immediately reflected in your UI control.

View Sorting & Filtering an XMLListCollection Example

Labels: ,

Friday, March 13, 2009

Flex Basics - ArrayCollection

Arguably one of the most useful constructs available to a Flex developer is an Array. Designed to store data of various types accessible via a numbered index, the Array class provides a useful mechanism for data storage and retrieval.

As such, an Array would appear to satisfy the data provider needs of any list-based control. However, it does not. Incompatibility with data binding makes an Array a poor choice of data provider. Fortunately, Flex provides a suitable alternative - ArrayCollection. An ArrayCollection provides all the features of an Array plus more.

To understand an ArrayCollection, one must first understand an Array.

Array

From Wikipedia, an Array "is a data structure consisting of a group of elements that are accessed via indexing". Arrays can store simple data types (primitives) such as number, boolean or string or complex data types such as other Arrays or objects.

In fact, Arrays defined in ActionScript (or MXML) are not strongly-typed and can store various types of data.

private var myArray:Array = new Array();
myArray[0"Tom"// string
myArray[12// number
myArray[2new Object()// object
Array elements can be retrieved or set using array access notation utilizing the zero-based index value of the desired element.

// retrieving the value of an array element
private var name:String = myArray[0];

// setting the value of an array element
myArray[0"Bill";
Note: Arrays are designed to use a numbered index. If you intend to retrieve data via a named index (i.e. Associative Array or HashMap), you may want to consider using an object as a data container. Unlike other classes, the Object class is dynamic - meaning arbitrary properties can be added to serve as keys.

var myObject:Object= new Object();
myObject.name = "Tom";
myObject.age = 27;
If your HashMap keys include spaces, use array access notation.

var myObject:Object= new Object();
myObject["first name"]"Tom";
HashMap values can be retrieved or set using dot notation (if no spaces in the key) or array access notation.

// retrieving the value of an object via an named index using dot notation
private var name:String = myObject.name;

// setting the value of an object property using dot notation
myObject.name = "Bill";

// retrieving the value of an object via an named index using array access notation
private var firstName:String = myObject["first name"];

// setting the value of an object property using array access notation
myObject["first name""Bill";
Arrays are dynamic and, therefore, can be resized simply by adding or removing elements.

// adds an element to the end of an array and increases the array length by one
myArray.push("Phil");

// removes the last element from an array and decreases the array length by one
myArray.pop();
ActionScript supports two methods for creating Arrays, each with a variety of syntaxes:

Method #1 – Create an Array by defining (or not defining) the number of elements

// creates an array with zero elements (this is the default when no argument is passed 
to the Array constructor)
private var myArray:Array = new Array();

// creates an array with 10 elements
private var myArray:Array = new Array(10);

// creates an array with zero elements using literal notation
private var myArray:Array = [];
Method #2 – Create an array by defining the array elements and their values

private var myArray:Array = new Array("red",2);
private var myArray:Array = ["red",2];
Note: The Array class can support both initialization techniques by providing two class constructors. The appropriate constructor is used based on the argument value(s) (or lack thereof).

Arrays can also be built using MXML:

<mx:Array id="myArray"/> <!--creates an array with zero elements-->

<mx:Array id="myArray"> <!--creates an array with three elements-->
   <mx:String>myString</mx:String> <!--string-->
   <mx:Number>98</mx:Number> <!--floating-point number-->
   <mx:Object name="Phil" age="27"/> <!--object-->
</mx:Array>
Like everything in Flex, an Array is an object and as such it contains a handful of useful properties and methods.

One property familiar to all developers is the length property. The length property represents the number of array elements.

private var myArray:Array = new Array(10);
private var numberOfArrayElements:uint = myArray.length; // 10
Note: Although each Array element contains an undefined value in this scenario, the length is still 10.

The length property can be very handy. One popular technique involves using the length property to dictate the number of loops included in a For Loop.

for (var i:uint; i < myArray.length; i++) {
   trace(myArray[i]);
}
Note: You can truncate an Array by setting the length property to a value less than the number of array elements. This is not true of an ArrayCollection as the length property is read-only.

By utilizing the methods of the Array class, you can perform a number of operations on the Array elements or the Array itself. Popular Array methods include:

* filter
* indexOf
* join
* push
* reverse
* slice
* sort
* toString

However, despite all of an Array's powerful features, the inability to support data binding is a significant shortcoming. Fortunately, Flex provides an ArrayCollection.

ArrayCollection

Per the Flex Language Reference, an ArrayCollection is a "wrapper class that exposes an Array as a collection that can be accessed and manipulated using the methods and properties of the ICollectionView or IList interfaces".

Two members of the ArrayCollection class are integral to the ArrayCollection's ability to support data binding - The collectionChange event and addEventListener method. To participate in data binding, an object must be able to:

1. dispatch an event when something changes
2. allow other objects to listen and respond to events

The ArrayCollection satisfies both thanks to the collectionChange event and the addEventListener method and will support data binding when given a compiler directive to do so using the [Bindable] metadata tag.

// creates a bindable ArrayCollection with zero elements
[Bindableprivate var myArrayCollection:ArrayCollection = new ArrayCollection();
An ArrayCollection can be created in one of three ways:

// creating ArrayCollection with zero elements
private var myArrayCollection:ArrayCollection = new ArrayCollection();

// passing an existing Array into an ArrayCollection via the constructor
private var myArrayCollection:ArrayCollection = new ArrayCollection(myArray);

// assigning an existing Array to the source property of an ArrayCollection
private var myArrayCollection:ArrayCollection = new ArrayCollection();
myArrayCollection.source = myArray;
Either method successfully wraps an Array inside an ArrayCollection and as such, extends the capabilities of an Array.

Note: In Flex, ActionScript classes can have optional constructor parameters only. MXML does not enforce required constructor parameters, therefore, if a constructor parameter is required to create a new instance of a class, provide a default value. In the case of an ArrayCollection, the default argument for the source parameter is NULL, hence, an empty ArrayCollection is created when the source parameter is omitted.

Extending the ListCollectionView class that implements the ICollectionView and IList interfaces, an ArrayCollection inherits a handful of properties, methods and events. Therefore, your plain old Array now has a new set of functionality.

New properties include (but not limited to):

* filterFunction
* length
* list
* sort
* source

New methods include (but not limited to):

* addEventListener
* addItem
* addItemAt
* contains
* getItemAt
* getItemIndex
* refresh
* removeAll
* removeItemAt
* setItemAt

Once an Array is wrapped inside an ArrayCollection, the properties and methods of the Array class are no longer accessible unless you access them through the Array object directly. For example, if you really want to use the Array's push method, you could do the following:

myArrayCollection.source.push("new element");
This would require using the ArrayCollection's refresh method to trigger data binding.

myArrayCollection.source.push("new element");
myArrayCollection.refresh();
However, you could always use the ArrayCollection's addItem method instead.

myArrayCollection.addItem("new element");
Realize that every ArrayCollection contains an Array as the data source. If you create an empty ArrayCollection and add elements using the methods of the ArrayCollection rather than assigning an Array to the source property of an ArrayCollection, an Array is created for you.

Any data manipulation performed on an ArrayCollection will be reflected in the underlying Array and vice-versa, however, it is important to note that manipulating an Array directly will not be reflected inside an ArrayCollection until you perform a refresh of the ArrayCollection using the ArrayCollection's refresh method.

Using an ArrayCollection in place of or in tandem with an existing Array provides Flex developers with a valuable and responsive data storage and retrieval mechanism.

Labels: ,