Reseting a Flex DataGrid's dataProvider when using a filterFunction

Submitted by Falken on

It's fairly common to have a filterFunction applied to the ArrayCollection you are displaying in a DataGrid, such as to hide deleted items:

dataGridData.filterFunction=stateFilterFunction;

I was also allowing users to edit and remove the displayed items; so needed a quick way for them to 'reset' all their unsaved changes, which lead to a couple of gotchas.

<mx:DataGrid dataProvider="{dataGridData}" editable="true" id="wipDG"
...

 

The first gotcha was fairly obvious in retrospect - when you are taking a backup copy before the user edits the data, you must get a real copy, not just another reference, by doing something like:

dataGridData = e.result.DATA;
dataGridDataBackup = ObjectUtil.copy( dataGridData ) as ArrayCollection;

This stops any changes made to the datagrid from also appearing in the backup copy by using ObjectUtil to create a new clone of the ArrayCollection.

We have to use 'as' to type the return from ObjectUtil.copy() as copy() works on any type so just returns an Object. We know we gave it an ArrayCollection so we know we'll get another one back.


Secondly, you need to make sure much the same thing happens when using ArrayCollection's removeAll() and addAll() methods, with the use of a filterFunction complicating things a bit more.
You might think it's as easy as

dataGridData.removeAll();
dataGridData.addAll( dataGridDataBackup.list );

but that causes a crash inside ListCollectionView !

The basic trick is to remove the filter and then reapply it at the end, otherwise all the operations only affect the current visible rows (so leaving rows behind).
You must also add a copy of the backup data, or (after one reset) changes to the DataGrid end up in the backup copy again.

dataGridData.filterFunction=null;
dataGridData.refresh();

dataGridData.removeAll();

dataGridData.addAll( ObjectUtil.copy( dataGridDataBackup ) as ArrayCollection );

dataGridData.filterFunction=stateFilterFunction;
dataGridData.refresh();

So, step by step what you have to do is:

  1. Remove the filter, and call refresh() just like the docs till you to do
  2. Remove all the existing records with removeAll()
  3. Add a copy of the backup of the data 
  4. Reenable the filter, and call refresh() again

 

This works really well as a quick 'undo' system for editable data sets in Flex, and seems to perform really well despite all the copying though I've not tested it with hundreds of rows; but loading that many items at once is a bit of a user experience fail anyway.

Sections