History | Log In     View a printable version of the current page.  
Issue Details (XML)

Key: SDK-15323
Type: Bug Bug
Status: Reopened Reopened
Priority: C C
Assignee: SDK Community
Reporter: Sergio Aguado
Votes: 5
Watchers: 6
Operations

If you were logged in you would be able to see more operations.
Flex SDK

The method setselectedItem of ComboBox doesn't take into account if the object you are trying to select implements IUID or not.

Created: 04/17/08 08:50 AM   Updated: 06/10/09 08:43 AM
Component/s: mx: ComboBox
Security Level: Public (All JIRA Users )

Severity: Incorrectly Functioning
Reproducibility: Every Time
Discoverability: High
Found in Version: SDK Flex 3.0.1
Milestone: SDK Community Fix Candidates
Affected OS(s): All OS Platforms - All
Steps to Reproduce:
The method setselectedItem of ComboBox doesn't take into account if the object you are trying to select implements IUID or not.


In the method setSelectedIndex of ComboboxBase there is a comparison with ==. The method should test if the objects you are passing implements IUID or not. If they implement both of them should be compared using the uid.

=====================================
private function setSelectedItem(data:Object, clearFirst:Boolean = true):void
    {
        //2 code paths: one for before collection, one after
        if (!collection || collection.length == 0)
        {
            _selectedItem = value;
            selectedItemChanged = true;
            invalidateDisplayList();
            return;
        }

        var found:Boolean = false;
        var listCursor:IViewCursor = collection.createCursor();
        var i:int = 0;
        do
        {
            if (data == listCursor.current) //THIS SHOULD BE CHANGED
            {
                _selectedIndex = i;
                _selectedItem = data;
                selectedUID = itemToUID(data);
                selectionChanged = true;
                found = true;
                break;
            }
            i++;
        }
        while (listCursor.moveNext());

        if (!found)
        {
            selectedIndex = -1;
            _selectedItem = null;
            selectedUID = null;
        }

        invalidateDisplayList();
    }
=====================================
 
Solution:
=======
Change line

if (data == listCursor.current)

with a method invocation and method like the following:

=====================================
if (equals(data,listCursor.current))

public function equals(a:Object,b:Object):Boolean{
if (a==null || b==null)
return false;

if (a is IUID)
if (b is IUID)
return a.uid == b.uid;
else
return false;
else
return a == b;
}
=====================================


I suppose that this kind of comparisons are spread across the code so please take that into account.

For developers I'm sure it's extremely important Flex and Actionscript to support equality.

Please try to solve this
Language Found: English
Bugbase Id: none
Triaged: Yes
Regression: No
QA Owner: Ella Mitelman
Participants: Ella Mitelman, Geoff Hichborn, Joan Lafferty, Ryan Holmes, SDK Community, Sergio Aguado and Tom Van den Eynde


 All   Comments      Sort Order:
Geoff Hichborn - [09/11/08 06:45 PM ]
This bug also affects mx:List

Ella Mitelman - [12/19/08 07:44 PM ]
Good to fix

Joan Lafferty - [02/19/09 11:23 PM ]
Internal Review -> This bug is getting deferred in Flex 4. It was discussed internally by a few developers and strong reasons for fixing it in this release were not voiced. In our new DataGroup classes for Flex 4, we are moving towards using indices rather than UUID to consider unique objects in that class.

 If more interest is shown in the future, then, we can reconsider this bug.

Ryan Holmes - [05/14/09 01:44 AM ]
The reason this needs to be fixed is because instance equality does not work when using remote objects. Consider the following common scenario: a list of Color remote objects is fetched from a server and used as the data provider for a "favorite color" ComboBox. That ComboBox is used in an edit form for a Person object's favoriteColor property (Person is also a remote object, fetched from a server). The Color object representing the Person's current favoriteColor will not match any of the instances in the data provider, so setting selectedItem="{myPersonObj.favoriteColor}" will not select correct item in the ComboBox. Instead, it will result in selectedIndex being set to -1.

If this bug was fixed and the Color object implemented IUID, the ComboBox would work as expected. With this bug, we must use boilerplate code every time we use a ComboBox to select the correct initial item (by searching through the items of the data provider and matching on UID or a custom equals() method). Or, in my case, we must use a custom subclass of ComboBox that provides this functionality.

The underlying problem here is that ActionScript provides no standard mechanism to compare objects by value rather than by instance (i.e. it lacks an equals() method). If Object had an equals() method, it would be the obvious way to check for equality in components like ComboBox, List, etc. Consistent use of the IUID interface to determine equality in Flex data components at least gives us a standard solution to this problem: implement IUID in your custom remote objects and return something like a primary key for the uid property.

I think there is a disconnect between Adobe developers and the users voting for this bug. What we want is a usable solution for value equality between selectedItem and the objects in a data provider. It sounds like you guys are focusing on the uniqueness of objects in a data provider. These are related but separate problems.

Ryan Holmes - [05/14/09 01:47 AM ]
Just wanted to add, now that SDK-14751 has been fixed, ComboBox should be fixed to provide consistent behavior. If IUID equality makes sense for a List, it surely makes sense for a ComboBox as well.

Joan Lafferty - [05/14/09 10:23 AM ]
We don't have time to fix this in our Flex 4 schedule, but, I'm going to target this for a community fix. It could make a good contribution from the community.

Tom Van den Eynde - [06/10/09 08:43 AM ]
This should indeed be fixed (actually already in Flex 2.01...).
Anyway some might be able to live with the following workaround for the time being (not perfect but it can probably be used in a number of cases):

<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.IList;
import mx.core.IUID;

override public function set selectedItem(data:Object):void
{
super.selectedItem = data;
if ((this.selectedIndex==-1)&&(data is IUID)&&(this.dataProvider is IList))
{
for (var i: int = 0; i < (this.dataProvider as IList).length; i++)
{
var item: Object = (this.dataProvider as IList).getItemAt(i);
if ((item is IUID)&&(item.uid==data.uid))
{
this.selectedIndex =i;
break;
}
}
}
}

]]>
</mx:Script>
</mx:ComboBox>