Observe the Flex program below (I’m using Flex Builder 3 w/ 3.5 SDK). The second combobox is conditional on the first. If a ‘first name’ is chosen, then you are allowed to choose a ‘last name’. If ‘none’ is chosen, then you are not allowed to choose a last name, but rather prompted to choose a first name.
To see the mysterious issue of the disappearing labels, run this program and choose a first name. Then choose a last name. All is well. Then choose ‘none’ in the first combobox. The prompt of the second combobox changes back, and the last names are removed. All is still well. Then try selecting a first and last name again. You will see that after choosing a first name, the last names do not appear, although the spaces for them do (and if you debug the program, the correct data appears in the dataprovider).
This ‘bug’ has been killing me on the inside all day. The project in which I’m implementing this behavior is quite a bit more complex, but this sample basically exemplifies what is going on. Is this a bug in Flex, or am I doing something wrong?
Thanks!
<?xml version="1.0" encoding="utf-8"?>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var cbCompanyDP:ArrayCollection = new ArrayCollection( [ { firstName: "None", data: 0 },
{ firstName: "Bob", data: 1 },
{ firstName: "Bart", data: 2 } ] );
[Bindable]
public var cbEmployeeDP:ArrayCollection = new ArrayCollection();
public var employees:ArrayCollection = new ArrayCollection( [ { lastName: "Smith" },
{ lastName: "Smyth" },
{ lastName: "Smick" },
{ lastName: "Smack" } ] );
[Bindable]
public var prompt:String = "Choose First Name first";
public function cbFirstNameChange( value:int ):void
{
if ( value == 0 )
{
employees.removeAll();
setEmpDP( employees );
prompt = "Choose First Name first";
}
else
{
setEmployees();
setEmpDP( employees );
prompt = "Now choose Last Name";
}
}
private function setEmpDP( ac:ArrayCollection ):void
{
cbEmployeeDP = ac;
}
private function setEmployees():void
{
employees = new ArrayCollection( [ { lastName: "Smith" },
{ lastName: "Smyth" },
{ lastName: "Smick" },
{ lastName: "Smack" } ] );
}
]]>
</mx:Script>
<mx:HBox>
<mx:ComboBox dataProvider="{cbCompanyDP}"
id="cbFirstName"
labelField="firstName"
width="200"
change="cbFirstNameChange(cbFirstName.selectedItem.data)"
prompt="Choose a first Name" />
<mx:ComboBox dataProvider="{cbEmployeeDP}"
id="cbLastName"
labelField="lastName"
width="200"
prompt="{prompt}" />
</mx:HBox>
The problem here is that there is a binding missing.
If you change the dataProvider of teh ComboBox, it does not change the dataProvider of the generated dropdown. So the box knows the new list, but the dropdown still handles the old.
To fix this, you have to subclass the ComboBox and override set dataProvider and get dataProvider (for symmetry).
To also update the width of the dropdown in case the ComboBox width changed, it is also necessary to override another function:
This way it works as it should.
if you want, you can in the set dunction check whether the selectedIndex is -1 (which on an editable box means that there is manually entered content), save it from super.text and restore it to super.text (and set the index to -1 again) once you have set the new dataProvider. Else the text in the input field will be lost or replaced by the first list element.