Seems like it is once a month where someone is having trouble setting the selectedItem of a ComboBox. The key is that the ComboBox does an exact reference match on the items in the dataProvider. It doesnt take the time to compare values within the dataProvider items with the values in the item you are setting as the selectedItem.
In other words, if you have an array of objects:
[{ firstName: "Alex", lastName: "Harris" }, { firstname: "Alex", lastName: "Harui"}, {firstName: "Alex", lastName: "Trebek"}]you can't just set:
selectedItem = { firstName: "Alex", lastName: "Harui }as that assigns the selectedItem to a different Object instance with the same values. The ComboBox class will simply look to see if there is a reference to that instance in its dataProvider, which there is not. Instead, you have to scan the dataprovider and match up values.
So many folks are doing this, that I decided to post an example so we don't have to keep writing that scan-the-dataprovider loop. This example tries for an exact match first, so if you know you'll never have an exact match you can save more time by cutting out that first call to super.selectedItem = value;
Test file source
Helper class source for Test file
Usual caveats apply.

This one has hit me before, and that is one of the times, where it is great, that the sources for flex are open (so we can see exactly why our code is failing).
Nice solution, you got there!
Thanks Alex !!
Wouldn't it be better to have some kind of 'selectedValue' property? Because most of the time you don't have a completely similar object but just 1 property of the object (an ID or a name). It's actually sad to see that effort was put in an advanced datagrid but that the current set of controls hasn't been improved...
------------
File an enhancement request. It should be easy to subclass and add your own though.
maybe it is better to use :
if ( ObjectUtil.compare( obj, value ) == 0 )
{
super.selectedItem = obj;
return;
}
----------------
My example support partial matching where you might only know a few properties. You are correct that it doesn't support sub-object property matching, but ObjectUtil.compare is very slow so I'd only use it as a last resort.
If you have an object that you know is in the dataprovider, then a simple === test will be faster and work correctly.
In fact, the only reason ( for me ) to use ObjectUtils.compare instead of "for loop" is because in MXML code, it breaks code highlighting when you use something like this : selectedItem={ { id:myObject.id } }
that's why I prefer using : selectedItem={ myObject }
at least in Flex 2 plugin for eclipse.
I agree using ObjectUtils.compare might be a bit more concise.
In any case I would prefer to see a swappable comparator used so users can support their own logic for comparison.
public interface Comparator {
function compare (a:Object, b:Object): int;
}
For example I might want to compare on a unique id rather than the entire object.
-----------------------
Alex responds:
These examples are not supported or maintained. The source code is available so you can modify it as you please.
thanks for the nice example Alex!
I recently had a client that wanted to store a coded data element for the selection in a combo box, like this:
I'm using XML to return stored values to the Flex application from the MySQL DB and needed to set the selectedItem based on the stored data element... so your solution was just what I was looking for
However, I could not get it to work correctly in my situation at first:
I tried binding the return value in the MXML component directly like this:
or like this:
each of these solutions caused the combo box to show the first item as the selectedItem
so, I moved the setter to Actionscript:
b49.selectedItem={data:UserRecords.section.(@name =='binfo').q1};
with the same result.
I was about to abandon the effort and write a method to figure out the selectedIndex instead when I decided to try one more time. I spent some time going over and over your original code in the component and was puzzled by the test for a negative condition at:
if (obj[p] !== value[p])
and at:
if (!nope)
I removed the negative indicator (!) in both of those lines and compiled my application again, reading in values for the combo boxes, and viola!! it works like a champ.
I deployed the application today, using your extended ComboBox for 160 instances and am happy to report its working great! I included credits for your work in the code documentation and comments.... thanks again!
A bug has been submited to flex team for this issue. You can vote for it here : http://bugs.adobe.com/jira/browse/SDK-14751
Hi Alex,
First thank you for this code... I've used a version of it and it has simplified how we interact with ComboBoxes... mission accomplished.
Now the issue: I've also read through your article on item renderers, specifically the "Custom Header Renderers (ComboBox)" one. I'm not able to get a merge of the two features working. I need to be able to specify the default/selected value for the Find version of the ComboxBox being used as/in a headerRenderer. Additionally, the selected value specifier can't be hardcoded, it has to be dynamic... i.e., the selected value is the User Preference default, etc... It isn't known until run time.
I know it must feel like a simpleton question, but I can't put your 2 examples together in a way that is working.
Thanks for the learning.
--------------------
Alex responds:
I'm not sure where the value you want to find is being stored, but it seems like you just need to wire this combo to it. You might get faster help asking on FlexCoders
The problem is if the dataProvider from database. I can not make it. Do you have a sample code for dataProvider from database?
-------------------
Alex responds:
There are examples in the doc. Ask on FlexCoders if you need more help
That you can't preselect a drop down value without extending a core component is completely asinine. This is core functionality. Arg!
That's just wonderful ! Thank you Alex :)
Most of the time when I find on the web some "easy" code it takes me about an hour to figure out how does it work, one more hour to try the example and another extra hour to apply that code on my own app.
Your class it's easy as copy-paste :) you rock! I finally could get rid of that nasty loop... in less than 10 minutes!
Flex sucks, it shouldn't be this hard to get and set items in a combobox.