views:

2094

answers:

4

Is there any reason why there isn't an addAll() function available when using ArrayCollections in Actionscript? I've been using for loops to individually add them one at a time using addItem(). Is this common or is there a more convenient way?

+1  A: 

There's no reason that it isn't there, it's just not there. If you changed your code to use a plain Array instead of an ArrayCollection, you can use the Array.concat method. Otherwise, the only option is addItem in a loop.

Tmdean
A: 

After some more investigation, it turns out that an ArrayCollection is just a wrapper for an Array and that you have access to the array via arrcoll1.source. This allows you to call concat. I was able to remove my for loop and use this instead.

var arrColl1 = new ArrayCollection(['x','y','z']);
var arrColl2 = new ArrayCollection(['a', 'b', 'c']);

arrColl1.source = arColl1.source.concat(arrColl2.source);

If you are concatenating an array, for example selectedItems in a list, you can do this:

arrColl1.source = arrColl1.source.concat(seletedItems);
shadenite
You should read the documentation again."The ArrayCollection object does not represent any changes that you make directly to the source array. Always use the ICollectionView or IList methods to modify the collection."
Tmdean
Couldn't I refresh the collection after using concat?
shadenite
I don't think it matters if you call refresh or not. Your code might actually work since you're replacing the entire internal array and not merely modifying it, but the Flex documentation is silent on the matter. (It's never a good idea to rely on undocumented behavior, at any rate.)
Tmdean
+2  A: 

By way of example, try dropping this into a container. Essentially, it seems that if you have to have a one liner, creating a new ArrayCollection with the source of the original plus the new data will work, at least in the case below. Attempts to manipulate the source directly don't seem terribly useful, at least for data binding purposes (and if no data binding or events are involved, its probably better to use an array anyway).

<mx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        [Bindable] public var collection:ArrayCollection = new ArrayCollection([
            2,6,4,6,7,8,9
        ]);

        public function addToCollection():void {
            collection.addItem(Number(collectionValue.text));
        }

        public function newCollectionWithAddition():void {
            collection = new ArrayCollection(collection.source.concat(Number(collectionValue2.text)));
        }

        public function addToCollectionSource():void {
            collection.source.push(Number(sourceValue));
        }

        public function addToCollectionSourceWithRefresh():void {
            collection.source.push(Number(sourceValue2));
            collection.refresh();
        }
    ]]>
</mx:Script>

<mx:HBox width="100%">
    <mx:PieChart width="300" height="300">
        <mx:series>
            <mx:PieSeries dataProvider="{ collection }" />
        </mx:series>
    </mx:PieChart>
    <mx:PieChart width="300" height="300">
        <mx:series>
            <mx:PieSeries dataProvider="{ collection.source }" />
        </mx:series>
    </mx:PieChart>
</mx:HBox>

<mx:HBox>
    <mx:TextInput id="collectionValue" />
    <mx:Button label="Add To ArrayCollection"
        click="addToCollection()"
        />
</mx:HBox>

<mx:HBox>
    <mx:TextInput id="collectionValue2" />
    <mx:Button label="Create New ArrayCollection with new value"
        click="newCollectionWithAddition()"
        />
</mx:HBox>

<mx:HBox>
    <mx:TextInput id="sourceValue" />
    <mx:Button label="Add To ArrayCollection Source"
        click="addToCollectionSource()"
        />
</mx:HBox>

<mx:HBox>
    <mx:TextInput id="sourceValue2" />
    <mx:Button label="Add To ArrayCollection Source with refresh"
        click="addToCollectionSourceWithRefresh()"
        />
</mx:HBox>
Ckhrysze
+2  A: 

I can add some historical nuance to this. Apparently, Adobe heard the Flex community and has responded. An addAll(addList:IList) method has been added to the ListCollectionView type in the Flex 3.4 SDK.

But just in case there are others who may still be looking for a one-liner equivalent that works across the board, here is my one-very-long-line go at it:

var arrColl1 = new ArrayCollection(['x','y','z']);
var arrColl2 = new ArrayCollection(['a', 'b', 'c']);

// Using Flex SDK version 3.4:
arrColl1.addAll( arrColl2 );

// Using any Flex SDK:
arrColl2.source.forEach(function(item:*, i:int, arr:Array):void { arrColl1.addItem(item); }, this);

This is essentially what the Flex implementation does, and should handle binding concerns correctly, although it is not necessarily the prettiest thing to look at.

Patrick