Adobe Flex arraycollection - apache-flex

I want to use single collection object to two different UI components. 1. Datagrid and 2nd is chart component. I dont want to change anything inside the arraycollection object but I want to use it at the same time with two different component with minor changes. I know we can use filter function some how but not sure how to apply filter to arraycollection object so that one component (datagrid) can use the original arraycollection object and second component (chart) used the modified one.
Thanks,

If you use the same ArrayCollection as the dataProvider for two different components, then any filter or sort applied to that ArrayCollection will show up in both components.
What you want to do cannot be done.
However, you can create multiple ArrayCollections based on the same source and apply filters to them differently. Conceptually something like this:
public var arrayCollection1 : ArrayCollection = new ArrayCollection();
public var arrayCollection2 : ArrayCollection = new ArrayCollection();
protected function onIGotTheArray(value:Array):void{
arrayCollection1.source = value;
arrayCollection2.source = value;
dataGrid.dataProvider = arrayCollection1;
chart.dataProvider = arrayCollection2;
}
Now you can apply a filter to the first arrayCollection without affecting the second arrayCollection, or vice versa.
This is the preferred approach in my experience.

Related

Alternative to data binding

As an alternative to binding an array collection to a data grid's data provider, could I assign the array collection as the data provider to the data grid on it's creation and everytime the array collection is updated execute invalidateProperties(); invalidateList(); to re-render the data grid?
Does my described approach make sense?
Does my described approach make sense?
Sort of. If you have an arrayCollection ( ac) defined using a get/set method, there is no reason you can't set the dataPRovider on your DataGrid in the set method, every time the data is changed.
If you do that, then you most likely will not have to update the properties or displayList of the DatGrid, because the mere fact of replacing the dataProvider will do it for you.
Something like this:
private var _ac : ArrayCollection;
public function get ac():ArrayCollection){
return this._ac;
}
public function set ac(value:ArrayCollection){
this._ac = value;
this.dataGrid.dataProvider = this.ac;
}
Bingo, every time that the ac value is updated, so will the dataProvider on the DataGrid.

How do I append an item to my dataProvider? (Flex)

What I would like to do is simply add to a dataProvider, but when I do, I get an error.
Here's the code I'm trying to run...
dg.dataProvider.addItem(obj.ResultSet.Result[i]);
It's inside a for loop, using i as the integer.
It works great doing...
dg.dataProvider = obj.ResultSet.Result
But that won't work for me, because I need to add to the dataprovider more than once. I'm getting results in batches of 10, and I need to add each batch to the dataProvider when it's received.
I also tried to to do...
var dgDP:dataProvider = new dataProvider();
But for some reason Flex doesn't recognize it...
Any ideas on how I can make this happen?
You have to initialize the dataProvider.
<mx:DataGrid creationComplete="onDGCreate(event)"/>
Script:
public function onDGCreate(e:Event):void
{
var dg:DataGrid = e.currentTarget as DataGrid;
dg.dataProvider = new ArrayCollection();
//or
dg.dataProvider = new XMLListCollection();
}
Now this will work:
dg.dataProvider.addItem(obj.ResultSet.Result[i]);
When you assign something other than ArrayCollection and XMLListCollection to the dataProvider property, it will be converted to an ICollectionView object. The only implementer of this interface is the ListCollectionView class (base class of ArrayCollection and XMLListCollection) which has addItem and addItemAt methods.
A dataProvider is a property which resides on many ListBased classes. It is not a data type. What is the data type of your dataProvider? IT can be XML, an array, an XMLListCollection, an ArrayCollection, an XMLList, or a generic object. [and I assume other data types are supported).
The 'how' you add something to your dataProvider depends entirely on the type of dataProvider you are using.
In Flex 4, the dataProvider objects must implement the IList interface, but in Flex 3 dataProviders are generic objects.
In your situation, since you already have the objects, I'd just loop over them and add them to an array or ArrayCollection and then use hat array as a dataProvider.

Flex 3 Using an ArrayCollection to Populate Both a Datagrid and a ComboBox

I use this arrayCollection to populate a Flex 3 Datagrid. I'd also like to use this arrayCollection to populate a comboBox with the Name node.
In the arrayCollection, I've got the Name listed twice. I've got two rows in the Datagrid.
If I set the ComboBox's labelfield to Name, then the Name will be listed twice in the ComboBox menu. Is there a way to use this arrayCollection and have each Name listed only once in the comboBox?
I can always make another loop and array collection for the Name, but I was wondering if there were a better way.
var i:uint;
for (i=0; i<myArray.length; i++){
myDGArray = [
{Name: myArray[i].Name, Subject: 'Math:', Pass: myArray[i].math_pass, Fail: myArray[i].math_fail},
{Name: myArray[i].Name, Subject: 'Reading:', Pass: myArray[i].reading_pass, Fail: myArray[i].reading_fail}
]
}
myAC=new ArrayCollection(myDGArray);
Thank you.
-Laxmidi
I'm a bit confused. Based on your code sample, the name will be listed twice in the ComboBox because the same name is used twice in your dataProvider.
You may want o consider converting your dataProvider to two separate ListCollectionView objects, provide different filtering on each object and use those each as se[separate dataProviders.
In psuedo code this is how I'd do it:
public var comboBoxCollection : ListCollectionView = new ListCollectionView(myAC );
public var dataGridCollection : ListCollectionView = new ListCollectionView(myAC );
The apply filtering on the comboBoxCollection to filter out entries with duplicate names. More info on collection filtering in the docs.

Flex : How to hide a row in AdvancedDataGrid?

I have an AdvancedDataGrid with a ArrayCollection as its dataProvider. For instance i have a CheckBox that allows me to show or hide certain rows in the AdvancedDataGrid.
Any idea how i could do that?
My suggestion would be to use your data provider's filterFunction property. Basically, you can give your data provider a function that will determine whether a given item in the ArrayCollection is excluded or not (if an item is excluded, it won't be displayed in the AdvancedDataGrid, in essence making it "invisible"). The docs for filterFunction can be found here.
What I'd suggest then is that checking the checkbox sets a property on the object in your data provider, which is then used by your filter function to include/exclude rows. Some (very rough) pseudocode follows:
private function checkboxClickHandler( event:MouseEvent ):void
{
/*
Based on the MouseEvent, determine the row
in the data grid you're dealing with
*/
myDataProvider[someIndex].checkboxFlag = myCheckBox.selected;
myDataProvider.refresh(); // calling refresh() re-applies the filter to
// account for changes.
}
private function myDataProviderFilterFunction( item:Object ):Boolean
{
// assuming we want the item to be filtered if checkboxFlag is true
return !item["checkboxFlag"];
}

flex multiple array collections with a single datasource

How can I populate multiple datagrids in flex with a single datasource that is filtered differently for each datagrid. I'm assigning the event.result from my remote object call to three different array collections, each with its own filter function. When I assign and refresh the filter functions, they each affect all array collections. So, the results of the last array collection refresh end up in all three datagrids.
You probably need to use ObjectUtil.copy on your event result to have 3 separate ArrayCollections, one for each DataGrid... otherwise they all point at the same memory location of the single ArrayCollection and any changes made to it will be reflected in all DataGrids.
var AC1:ArrayCollection = event.result as ArrayCollection;
var AC2:ArrayCollection = ObjectUtil.copy(AC1) as ArrayCollection;
var AC3:ArrayCollection = ObjectUtil.copy(AC1) as ArrayCollection;
I would make copies of your data provider, ie:
var myDataArray:Array; // this contains your original data.
dataGrid1.dataProvider = new ArrayCollection(myDataArray.concat());
dataGrid2.dataProvider = new ArrayCollection(myDataArray.concat());
dataGrid3.dataProvider = new ArrayCollection(myDataArray.concat());
The solutions that have been provided may not behave as you might wish they would. An ArrayCollection technically consists of a model and a "view" into the model. In my understanding, both the solutions that have been provided create a copy of the model. This means if you add an item to one ArrayCollection it won't show up in another regardless of whether it would match that ArrayCollection's filter. Usually you want it to be a part of the model of the other ArrayCollections as well but only be visible if the added item passes the respective ArrayCollection's filter. You can share the "model" amongst ArrayCollections while having separate views into the model like so:
var collection1:ArrayCollection = new ArrayCollection();
var collection2:ArrayCollection = new ArrayCollection();
collection2.list = collection1.list;
var collection3:ArrayCollection = new ArrayCollection();
collection3.list = collection1.list;
Now you can add an item to any of the three collections and it will show up in the others. However, you can have separate filters and sorts on each individual ArrayCollection and that won't affect what's viewable in the others. You can read more about this here:
http://aaronhardy.com/flex/collections-and-chaining-for-separate-presentation/

Resources