February 18th, 2008 by Kyle
Tags: datagrid, Flex, idropinlistitemrenderer, ifocusmanagercomponent, itemeditor, itemrenderer
Posted in: Flex
Here is a sample that came about as usual, from working on an issue with a customer. I found I didn’t have a good example of a combobox itemEditor. This sample came about when moving from using a combobox as an inline editor to moving to a combobox within a custom component as an editor. Wrapping the combobox in a VBox within the custom component caused some errors and undesirable behavior. In order to wire up data and tabbing/focus behavior you have to remember you component should implement IDropInListItemRenderer and IFocusManagerComponent. See the following sample code and running sample:
App:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:XML id="xml" source="weather.xml"/>
<mx:DataGrid id="myDatagrid" dataProvider="{xml.city}"
variableRowHeight="true" editable="true" rowHeight="50"
width="300" height="300">
<mx:columns>
<mx:DataGridColumn dataField="Location"/>
<mx:DataGridColumn dataField="Climate" editable="true" editorDataField="value">
<mx:itemEditor>
<mx:Component>
<mx:ComboBox editable="true">
<mx:dataProvider>
<mx:String>Mild</mx:String>
<mx:String>Hot</mx:String>
<mx:String>Foggy</mx:String>
<mx:String>Rainy</mx:String>
<mx:String>Snow</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
<mx:DataGridColumn dataField="CloudCoverPercent" editable="true" editorDataField="value"
itemEditor="CloudCover"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Custom component:
implements="mx.controls.listClasses.IDropInListItemRenderer,mx.managers.IFocusManagerComponent">
<mx:Script>
<![CDATA[
import mx.controls.listClasses.ListData;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.dataGridClasses.DataGridItemRenderer
import mx.events.FlexEvent;
private var _listData:DataGridListData;
// Define a property for returning the new value to the cell.
[Bindable]
public var value:Object;
// Implement the drawFocus() method for the VBox.
override public function drawFocus(draw:Boolean):void {
cbo.setFocus();
}
override public function get data():Object {
return super.data;
}
override public function set data(value:Object):void {
cbo.data=value[_listData.dataField];
}
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = DataGridListData(value);
}
]]>
</mx:Script>
<mx:Binding destination="value" source="cbo.value"/>
<mx:ComboBox id="cbo" editable="true" width="100%">
<mx:dataProvider>
<mx:String>0</mx:String>
<mx:String>25</mx:String>
<mx:String>50</mx:String>
<mx:String>75</mx:String>
<mx:String>100</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:VBox>
XML data:
<weather>
<city>
<Location>Los Angeles</Location>
<Climate>Mild</Climate>
<CloudCoverPercent>25</CloudCoverPercent>
</city>
<city>
<Location>San Francisco</Location>
<Climate>Hot</Climate>
<CloudCoverPercent>50</CloudCoverPercent>
</city>
<city>
<Location>Paris</Location>
<Climate>Foggy</Climate>
<CloudCoverPercent>0</CloudCoverPercent>
</city>
<city>
<Location>Milan</Location>
<Climate>Hot</Climate>
<CloudCoverPercent>25</CloudCoverPercent>
</city>
<city>
<Location>London</Location>
<Climate>Rainy</Climate>
<CloudCoverPercent>100</CloudCoverPercent>
</city>
<city>
<Location>New York</Location>
<Climate>Snow</Climate>
<CloudCoverPercent>50</CloudCoverPercent>
</city>
<city>
<Location>Sydney</Location>
<Climate>Hot</Climate>
<CloudCoverPercent>50</CloudCoverPercent>
</city>
<city>
<Location>CapeTown</Location>
<Climate>Mild</Climate>
<CloudCoverPercent>100</CloudCoverPercent>
</city>
</weather>
Browse the source of this example.
Download a zipfile containing the source to this sample.











February 22nd, 2008 at 1:23 am
Is there a way that you can change the first column(Location) to not loop through each element in the grid after renaming one?
Johan
February 22nd, 2008 at 1:26 am
And allso, is there a way to enable double-click to edit an item in the Locations column?, not single click.
March 10th, 2008 at 2:36 pm
I am not sure what you mean by your first question.
As for double clicking a datagrid entry to edit, see: http://blogs.adobe.com/aharui/2008/03/datagrid_doubleclick_to_edit.html
March 24th, 2008 at 2:17 am
Can canvas be item editor? how to make more than one header and it can be merge?
March 25th, 2008 at 12:15 pm
That’s not what I am trying to demonstrate here. I suggest you look at the docs on how to create itemEditors. You could wrap the combobox in canvas if you want, but then have to deal with positioning it.
As for merged headers, you may want to check out this blog post:
http://blogs.adobe.com/aharui/2007/03/thinking_about_item_renderers_1.html
or look at the AdvancedDataGrid in Flex3
April 4th, 2008 at 11:35 am
hi Kyle,
i have an similare requirement as in the above example to do. In the above example i have to use Datefield insted of combo box. how can i do??? can u help me on this??
thanks in advance
PEter
April 8th, 2008 at 12:57 pm
I have just posted a new blog post that should help you out using a DateField as an itemEditor in a DataGrid: http://blog.flexmonkeypatches.com/2008/04/08/datefield-itemeditor-when-date-is-a-string/
April 28th, 2008 at 3:50 pm
I would like to specify the dataProvider for ComboBox cbo, instead of populating it with an Array of String. Presumably the definition of the item renderer would change to something like this:
// new line:
[Bindable] public var dataProvider:Array;
// replace definition of CombBox with this:
<mx:ComboBox id=”cbo” editable=”false” width=”100%” dataProvider=”{dataProvider}” />
My program calls from ActionScript, something like this:
var columns:Array = new Array();
columns[0] = new DataGridColumn();
columns[0].dataField = “Species”;
columns[0].editable = false;
columns[1] = new DataGridColumn();
columns[1].dataField = “Lifestage”;
columns[1].headerText = “Life Stage”;
columns[1].itemEditor = CrudDataItemRenderer;
# Need to specify dataProvider for combobox somehow here
myDataGrid.columns = columns
Any suggestions?
April 28th, 2008 at 4:34 pm
correction to my second last line of code:
columns[1].itemEditor = new ClassFactory(CrudDataItemRenderer);
… where CrudDataItemRenderer is the item renderer for my data grid.
I found this (http://livedocs.adobe.com/flex/3/langref/mx/core/ClassFactory.html) to be helpful. I added the following line (app.species.lifeStages is an ArrayCollection):
columns[1].itemEditor.properties = { dataProvider: app.species.lifeStages.source };
Problem solved!
June 10th, 2008 at 12:27 am
There is another way Mike, to the original code: DataGrid add itemEditBegin=”testing(event);”
create a function in your script along with your dataprovider
[Bindable]
public var dataprovider:XML = new XML (025);
private function testing(event:DataGridEvent):void
{
myDatagrid.createItemEditor(event.columnIndex,event.rowIndex);
itemeditorcombobox(myDatagrid.itemEditorInstance).cbo.dataProvider = dataprovider..temp;
}
Of course the definition for your combobox within the vbox remains essentially the same eg:
For some odd reason that I haven’t worked out though, none of the items in the combobox are default selected? Further with the set up as above you must have editable set to true on the combobox. Very frustrating!
All of this is such a work around, why couldn’t flex3 allow us to put an inline editor as a combobox with a different dataProvider to the datagrid in which it is nested???
June 10th, 2008 at 12:29 am
Please substitute your own XML for the dataprovider as the comments do not apparently allow for submission of XML code.
Don’t forget to import mx.events.DataGridEvent;
good luck
September 15th, 2008 at 10:37 pm
@Mike, @Ian:
You need to use:
September 15th, 2008 at 10:39 pm
code was striped from last comment.
Lets try again:
You need to use {outerDocument.myComboBoxData}
Apparently, the mx:Component tag defines a new scope in an MXML file. The solution is to use the outerDocument keyword.
September 20th, 2008 at 7:17 pm
I’m having a problem with the
CollectionEventKind.UPDATE not being fired when the column that the ComboBox resides is sorted by the end user.
There is a CollectionEventKind.MOVE fired instead of the UPDATE.
This poses a bit of a problem for me. I’m saving this data back to a DB and have to pass in the windows user who modified it.
The data is actually changing, but since I never see the event, I can’t write back who changed it.
I’ve searched low and high and can’t seem to find any info on this.
fyi… Everything works as expected when the column in not sorted by the end user.
Great example!
Thanks in advance for any help!