Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
Adobe Flex SDK 3.6 (Release)
-
Affected OS(s): All OS Platforms
Browser: Firefox 3.x
Language Found: English
Description
Note: issue affects several version of Flex SDK, first noticed in 3.4, but same problem exists in latest stable build of 4.0 as well.
Steps to reproduce:
1. Use mx:List control with dataProvider containing non-primitive items (like Date, for simplest case)
2. Use selectedItemsCompareFunction on mx:List to compare items during selection
3. Set selectedItems as an array of objects with references different to ones used in dataProvider
Actual Results:
Runtime exception thrown:
TypeError: Error #1010: A term is undefined and has no properties.
at mx.controls.listClasses::ListBase/setSelectionDataLoop()[C:\autobuild\3.4.0\frameworks\projects\framework\src\mx\controls\listClasses\ListBase.as:6473]
at mx.controls.listClasses::ListBase/commitSelectedItems()[C:\autobuild\3.4.0\frameworks\projects\framework\src\mx\controls\listClasses\ListBase.as:6364]
at mx.controls.listClasses::ListBase/set selectedItems()[C:\autobuild\3.4.0\frameworks\projects\framework\src\mx\controls\listClasses\ListBase.as:2942]
at ListsCompare/updateLeft()[C:\Documents and Settings\sav\Adobe Flash Builder Beta 2\FileDownload\src\ListsCompare.mxml:22]
at ListsCompare/__lstRight_change()[C:\Documents and Settings\sav\Adobe Flash Builder Beta 2\FileDownload\src\ListsCompare.mxml:37]
....
Expected Results:
selection is applied correctly
Reason and possible resolution:
Actually bug fix is super easy. The problem itself lies in fact that List temporary stores UID-to-index map of selected items in one function
function commitSelectedItems(items:Array):void
{...}and afterward applies it incorrectly in another
function setSelectionDataLoop(items:Array, index:int, useFind:Boolean = true):void {...}
Namely, the following lines causes the problem (from setSelectionDataLoop):
if (compareFunction(data, item))
{
uid = itemToUID(data); // ISSUE IS HERE – must be itemToUID(item)
selectionDataArray[proposedSelectedItemIndexes[uid]] = new ListBaseSelectionData(data, index, false);
...
}
I.e. proposedSelectedItemIndexes is indexed by UID of objects from selectedItems but here it is accessed by UID of objects from dataProvider.
Workaround (if any):
Given the fact that comparator is invoked right before call to itemToUID and comparator is never used in any other place, mx:List may be replaced with custom class with the following trick applied:
package {
import mx.controls.List;
public class MyList extends List {
override public function set selectedItemsCompareFunction(value:Function):void {
super.selectedItemsCompareFunction = value == null ? null : function(a:, b:):Boolean
;
}
private var isComparatorCalled:Boolean = false;
private var latestComparatorParam:* = null;
override protected function itemToUID(data:Object):String {
if (!isComparatorCalled)
return super.itemToUID(data);
else
}
}
}