Alternative to data binding - apache-flex

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.

Related

Adobe Flex arraycollection

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.

Setting dataProvider to a comboBox

When setting an arrayCollection as a dataProvider to a comboBox programmatically,if the arrayCollection has just one element,i need to do a small validation:
> public resultHandler(event:ResultEvent):void{
arrColl = event.result.FlexData.ListData as ArrayCollection;
//to check if the arrColl has only one element
if(arrColl == null)
myComboBox.dataProvider = event.result.FlexData.ListData
else
myComboBox.dataProvider = arrColl;
}
I would like to know,if there is a way to skip this validation every time.Is there a way to set dataProvider such that i dont have to check if the collection has one or more elements?
There is no built-in way to do this.
You'll need to either:
create a utility method that does this. For instance
myComboBox.dataProvider = ComboBoxUtil.setDataProvider(collection);
subclass the ComboBox control and override the dataProvider setter where you can include this logic

Why change in ArrayCollection's length doesn't invoke Setter on component using it as data source?

I have a component where I expose the property 'questions' with the following code:
private var _questions:ArrayCollection;
private var questionsChanged:Boolean;
[Bindable("questionsChanged")]
public function get questions():ArrayCollection {
return _questions;
}
public function set questions(value:ArrayCollection):void {
if (_questions != value) {
_questions = value;
questionsChanged = true;
invalidateProperties();
dispatchEvent(new Event("questionsChanged"));
}
}
In this component, I use commitProperties() to implement my logic.
I use Cairngorm and the 'questions' is in the model and hence it's defined as a source for data binding.
When the 'questions' ArrayCollection's size changes elsewhere in the application, it is not invoking the setter method in the component that is destination for the data binding.
Could someone help me understand why this is the case?
You'll have to show the code where you are changing the array collection. But, this will fire the setter:
questions = somethingArrayCollection();
This will not:
questions.addItem(newQestion)
The questions variable is, basically, a pointer. Changing the thing that the variable points to does not need the set event.
I suggest you look at the CollectionChangeEvent, which the ArrayCollection fires when items are added to and from that. Listen to the event and perform your 'change' actions in the event handler. ( or tie into the lifecycle and invalidate some flag and perform your changes in commitProperties() )

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 : 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"];
}

Resources