Saturday, February 5, 2011

Using an ArrayCollection original data after applying a filter function

Many times developers want to apply filtering functions to an ArrayCollection. However, there might be several components or functions which use this very same ArrayCollection for data binding. When this is the case, and a filtering function is applied to the ArrayCollection, all components bind to the ArrayCollection reflect the filtering, which might not be something the developer wants or expects to happen.


The reason why this happens is because the ArrayCollection acts as a wrapper to its source Array. When a filtering function is applied to the ArrayCollection, the filtered out objects are hidden by the wrapper. However, all original objects can still be accessed by using the ArrayCollection’s source array.


The following example illustrates the issue. There is an ArrayCollection, itemsAC, to which we apply the filter function “showOnlyFruits”. 


[Bindable]
/*
 * DataProvider for the combobox
 *
 * @public
 */
public var itemsAC:ArrayCollection = 
 new ArrayCollection([{label: "banana", type: "fruit"},
                     {label: "mango", type: "fruit"},
                     {label: "lettuce", type: "vegetable"},
                     {label: "spinach", type: "vegetable"}]);
private function toggleItemsVisibility():void{
   // only show fruits
   itemsAC.filterFunction = showOnlyFruits;
   itemsAC.refresh();
}
private function showOnlyFruits(p_item:Object):Boolean
{
   return (p_item.type == "fruit") ? true : false;
}
After the filter function gets executed, we can check the length of both the ArrayColeciton and its source.


trace(this.itemsAC.length); //2
trace(this.itemsAC.source.length); //4

As you can notice, the ArrayCollection only has 2 items, the filtered ones. But the source array has all of the original items available.

Sunday, September 19, 2010

Using HTML formatting when binding variables in MXML

A while ago, I was creating a component that had a repeater, whose  data provider was composed of objects with of 3 strings, and I wanted to format differently each string. This is a sample output of my repeater:



Item 1: small - $1 
Item 2: Medium - $2
Item 3: large - $3

The first string in each object is bolded, the second is italicized, and the third is colored blue.
The first attempt to obtain these results failed, and it looked like this:

<mx:Repeater id="myRepeater"
    dataProvider="{itemsAC}"
    recycleChildren="true"
    height="100%"
    width="100%">
    <mx:Text>
        <mx:htmlText>
            <![CDATA[Item <b>{myRepeater.currentItem.id}</b>: <i>{myRepeater.currentItem.size}</i> - <font color="#005D84">{myRepeater.currentItem.price}</font>]]</mx:htmlText>
    </mx:Text>
</mx:Repeater>
The code above successfully styles the text, but the binding does not work. The following output is displayed when the above code is run:


Item {item.id}: {item.size} - {item.price}
Item {item.id}: {item.size} - {item.price}
Item {item.id}: {item.size} - {item.price}
After investigating a bit further, I came up with the solution to this problem, where both the styling of the text and the data binding work:


<mx:Repeater id="myRepeater"
    dataProvider="{itemsAC}"
    recycleChildren="true"
    height="100%"
    width="100%">
    <mx:Text id="warningText"
        htmlText="Item &lt;b&gt;{myRepeater.currentItem.id} - &lt;/b&gt; {messageRepeater.currentItem.size} - &lt;font color=&quot;#005D84&quot;&gt;{messageRepeater.currentItem.price}&lt;/font&gt;"/>
</mx:Repeater>
In order to do binding, MXML should be used. However, HTML tags don't work in MXML, you have specify HTML markup by using the &lt;, &gt;, and &amp; character entities in place of the left angle bracket (<), right angle bracket (>), and ampersand (&) HTML delimiters.  For more information on this, check put the adobe livedocs: 
http://livedocs.adobe.com/flex/3/html/help.html?content=textcontrols_08.html


There are several other ways to accomplish this outcome,and this is just one of them. I hope I have saved  you some time by sharing this solution  :-)