Monday, March 22, 2010    
Home My Books Blog ColdFusion About Me Back    

Calendar
<< Nov 2006 >>
S M T W T F S
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    

Search

Categories
 • Acrobat (3) [RSS]
 • Adobe (90) [RSS]
 • AdobeMAX06 (45) [RSS]
 • AdobeMAX07 (59) [RSS]
 • AdobeMAX08 (66) [RSS]
 • AdobeMAX09 (39) [RSS]
 • AdobeMAX10 (1) [RSS]
 • AIR (219) [RSS]
 • Appearances (191) [RSS]
 • Books (72) [RSS]
 • CFEclipse (15) [RSS]
 • ColdFusion (1382) [RSS]
 • Data Services (34) [RSS]
 • Fish Tank (5) [RSS]
 • Flash (198) [RSS]
 • Flex (499) [RSS]
 • Home Automation (5) [RSS]
 • Jobs (116) [RSS]
 • JRun (14) [RSS]
 • Labs (43) [RSS]
 • LiveCycle (34) [RSS]
 • MAX (232) [RSS]
 • Mobile (120) [RSS]
 • Regular Expressions (17) [RSS]
 • RIA (21) [RSS]
 • SQL (40) [RSS]
 • Stuff (536) [RSS]
 • Tips (CF Studio) (80) [RSS]
 • Tips (CF) (795) [RSS]
 • Tips (Dreamweaver) (91) [RSS]
 • Tips (Flex Builder) (2) [RSS]
 • Using CF (162) [RSS]

Other BLOGs
 • Charlie Arehart
 • Lee Brimelow
 • Ray Camden
 • Christophe Coenraets
 • Sean Corfield
 • Mihai Corlan
 • Cornel Creanga
 • Mark Doherty
 • John Dowdell
 • Danny Dura
 • Enrique Duvos
 • Steven Erat
 • Kevin Hoyt
 • Serge Jespers
 • Adam Lehman
 • Duane Nickull
 • Miti Pricope
 • Andrew Shorten
 • Ryan Stewart
 • James Ward
 • Greg Wilson
 • Full As A Goog

RSS Feeds
 • Feed
 • Subscribe

Join my mailing list and find out about new books and other topics of interest.

Thoughts, ideas, tips, musings, and pontifications (not necessarily in that order) by Ben Forta ...
NOTE: This is my personal blog, and the opinions and statements voiced here are my own.

Viewing By Entry / Main
November 22, 2006

Flex ComboBox With selectedValue Support

One of the things I like most about ColdFusion's <CFSELECT> tag is the SELECTED attribute, give it a value and it figures out which one to pre-select. The Flex ComboBox allows you to set selectedIndex (the relative element position) but not selectedValue. Actually, ComboBox does have a selectedValue property, but that is used to read the value of the selected item, and can't be used to set the value of the item to be selected.

Coincidentally, while I was working on this, both Scott Stroz and Ray Camden posted solutions to the exact same problem. Scott's solution involved calling a method to set the value, and I really think that the selectedValue property should be used to be consistent with how ComboBox itself works. Ray's solution allows for a property to be set (he defined a new property for this), but his solution would not work for me as my dataProvider was being populated after the control had been created (it is being populated by a call to a CFC).

So, here is my solution. It's bit more complex than what Scott and Ray suggested, but it does support selectedValue, it'll also allow that property to be changed as needed (even after control creation), and it also properly handles delayed dataProvider population.

Here is the code:

<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            private var _selectedValue:String;
            private var bSelectedValueSet:Boolean = false;
            private var bDataProviderSet:Boolean = false;

            // Override committ, this may be called repeatedly

            override protected function commitProperties():void
            {
                // invoke ComboBox version

                super.commitProperties();

                // If value set and have dataProvider

                if (bSelectedValueSet && bDataProviderSet)
                {
                    // Set flag to false so code won't be called until selectedValue is set again

                    bSelectedValueSet=false;
                    // Loop through dataProvider

                    for (var i:int=0;i<this.dataProvider.length;i++)
                    {
                        // Get this item's data

                        var item:String = this.dataProvider[i].data;
    
                        // Check if is selectedValue

                        if(item == _selectedValue)
                        {
                            // Yes, set selectedIndex

                            this.selectedIndex = i;
                            break;
                        }
                    }
                }
            }

            // Trap dataProvider being set

            override public function set dataProvider(o:Object):void
            {
                // invoke ComboBox version

                super.dataProvider = o;

                // This may get called before dataProvider is set, so make sure not null and has entries

                if (o!=null && o.length)
                {
                    // Got it, set flag

                    bDataProviderSet = true;
                }
            }

            // set for selectedValue

            public function set selectedValue(s:String):void
            {
                // Set flag

                bSelectedValueSet = true;
                // Save value

                _selectedValue = s;
                // Invalidate to force commit

                invalidateProperties();
            }
        ]]>

    </mx:Script>

</mx:ComboBox>

And here is a simple test case:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:ns1="*">
<mx:Script>
    <![CDATA[
        [Bindable]
        private var comboData:Array=
        [{label:"Item1", data:"1"},
        {label:"Item2", data:"2"},
        {label:"Item3", data:"3"}];
    ]]>

</mx:Script>
<ns1:ComboBox2 dataProvider="{comboData}" selectedValue="3" />
</mx:Application>

Related Blog Entries

TrackBacks
There are no trackbacks for this entry.

No trackback URL. Trackbacks are only allowed via interactive form.

Comments
I dont get it. Im using this component NEXT to a datagrid. I select a row in the datagrid and the ComboBox changes how I want it to. But now I want to be able to change the combobox and sent that to a server but I can only seem to get the index. I want the label and data. when I use code hinting, It shows me that I can now use the slectedValue but it causes an error. How do I see all the values assosiated with the combo box, Label, Data?
# Posted By George | 6/26/09 12:00 PM
In my flex app, I have 2 datagrids and when the app opens both datagrids get populated with data, dg2 visibilty is set to false; dg1 visibility is set to true. When the user clicks on a row in dg1, it populates combo boxes with that row data. That all works according your suggestion above (Thx!). I have a button, when clicked, it makes visible dg2. When I click on the button, dg2 becomes visible but then I want to be able to populate the same combo boxes with the row data in dg2. However, I've tried it and nothing gets selected in the combo boxes. any suggestions or examples? I'm using flex 3. Any help is appreciated.
# Posted By Mike | 6/26/09 4:59 PM
In my flex app, I have 2 datagrids and when the app opens both datagrids get populated with data, dg2 visibilty is set to false; dg1 visibility is set to true. When the user clicks on a row in dg1, it populates combo boxes with that row data. That all works according your suggestion above (Thx!). I have a button, when clicked, it makes visible dg2. When I click on the button, dg2 becomes visible but then I want to be able to populate the same combo boxes with the row data in dg2. However, I've tried it and nothing gets selected in the combo boxes. any suggestions or examples? I'm using flex 3. Any help is appreciated.
# Posted By Mike | 6/26/09 4:59 PM
Hi, Thanks your example, And I made a little change of yours, I think it will be more convenient

override protected function commitProperties():void
{
// invoke ComboBox version

super.commitProperties();

// If value set and have dataProvider

if (bSelectedValueSet && bDataProviderSet)
{
// Set flag to false so code won't be called until selectedValue is set again

bSelectedValueSet=false;
// Loop through dataProvider

for (var i:int=0;i<this.dataProvider.length;i++)
{
// Get this item's data

var item:String = this.dataProvider[i][this.data]; //The little change

// Check if is selectedValue

if(item == _selectedValue)
{
// Yes, set selectedIndex

this.selectedIndex = i;
break;
}
}
}
}

In this way , Our value field name of our dataprovider can not be data but the other name.
thank you.
# Posted By Gary | 8/13/09 3:52 AM
Thanks a lot....

For Xml list
=============================================
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"; xmlns:ns2="myComponents.*">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.core.IFlexDisplayObject;
private var helpWindow:IFlexDisplayObject;
private var books:XML = <books>
<book publisher="Addison-Wesley" name="Design Patterns" ids="0"/>
<book publisher="Addison-Wesley" name="The Pragmatic Programmer" ids="1"/>
<book publisher="Addison-Wesley" name="Test Driven Development" ids="2"/>
<book publisher="Addison-Wesley" name="Refactoring to Patterns" ids="3"/>
<book publisher="O'Reilly Media" name="The Cathedral & the Bazaar" ids="4"/>
<book publisher="O'Reilly Media" name="Unit Test Frameworks" ids="5"/>
</books>;
private function his():void {
xselect.selectedValue = "5";
}
]]>
</mx:Script>
<ns2:xmlcmbbox id="xselect" dataProvider="{books.book}" labelField="@name" />
<mx:Button click="his();" label="hiss"/>
</mx:Application>
=============================================================
<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml";>
<mx:Script>
<![CDATA[
private var _selectedValue:String;
private var bSelectedValueSet:Boolean = false;
private var bDataProviderSet:Boolean = false;
// Override committ, this may be called repeatedly
override protected function commitProperties():void {
// invoke ComboBox version
super.commitProperties();
// If value set and have dataProvider
if (bSelectedValueSet && bDataProviderSet) {
// Set flag to false so code won't be called until selectedValue is set again
bSelectedValueSet=false;
// Loop through dataProvider
for (var i:int=0;i<this.dataProvider.length;i++){
// Get this item's data
var item:String = this.dataProvider[i].@ids;
// Check if is selectedValue
if(item == _selectedValue) {
// Yes, set selectedIndex
this.selectedIndex = i;
break;
}
}
}
}
// Trap dataProvider being set

override public function set dataProvider(o:Object):void {
// invoke ComboBox version
super.dataProvider = o;
// This may get called before dataProvider is set, so make sure not null and has entries
if (o!=null && o.length) {
// Got it, set flag
bDataProviderSet = true;
}
}

// set for selectedValue
public function set selectedValue(s:String):void {
// Set flag
bSelectedValueSet = true;
// Save value
_selectedValue = s;
// Invalidate to force commit
invalidateProperties();
}
]]>
</mx:Script>
</mx:ComboBox>
============================================================
# Posted By Navis Michael Bearly | 9/25/09 4:21 AM
Thanks so much for this. Why didn't Adobe do this it seems so obvious!
# Posted By Chris | 9/29/09 12:18 PM
Why would I get always get [object Object] when I switch from the regular combobox to this one? I am using a webservice connected to a CFC.
# Posted By John | 10/24/09 11:01 PM
I guess we can use selectedIndex={x.y} in combobox with y as part of data source xml itself.
# Posted By kid | 11/30/09 10:17 AM
Very close to what I want to do.

This solution works until you set the combobox to be editable.

What I am trying to has three indexes in the combobox (-1, 0, and one that the user can type in a value). Using your solution I can make the combobox value aware, but as soon as I flag the combobox as editable it will no longer lets me submit a value.

Does anyone have a work around for that?
# Posted By David Brannan | 12/6/09 3:30 AM
Thanks! Just what I needed.
# Posted By Chris | 1/29/10 3:59 AM

  © Copyright 1997-2009 Ben Forta, All Rights Reserved