Flex DataGrid Editing Cells
Flex datagrids provide an easy way to edit data. However one minor issue is that by default editable cells have no visual indication that they are actually editable.
You can add a graphical or textual indication that is a cell is editable with an item renderer.
Here's the code to do this:
1<?xml version="1.0" encoding="utf-8"?>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()" viewSourceURL="srcview/index.html">
3
4 <mx:DataGrid id="myDG" dataProvider="{customers}" rowCount="5" width="300" height="200" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn headerText="Name" width="100" dataField="name" editable="false" editorDataField="text">
7 <mx:itemRenderer>
8 <mx:Component>
9 <mx:HBox horizontalScrollPolicy="off">
10 <mx:Label text="{data.name}" />
11 <mx:Spacer width="100%" />
12 <mx:Label text="+" click="outerDocument.editCell(0)" toolTip="Edit" />
13 </mx:HBox>
14 </mx:Component>
15 </mx:itemRenderer>
16 <mx:itemEditor>
17 <mx:Component>
18 <mx:TextInput text="{data.name}" />
19 </mx:Component>
20 </mx:itemEditor>
21 </mx:DataGridColumn>
22
23 <mx:DataGridColumn headerText="Addresss" dataField="address" width="200" editable="false" editorDataField="text">
24 <mx:itemRenderer>
25 <mx:Component>
26 <mx:HBox horizontalScrollPolicy="off">
27 <mx:Label text="{data.address}" />
28 <mx:Spacer width="100%" />
29 <mx:Label text="+" click="outerDocument.editCell(1)" toolTip="Edit" />
30 </mx:HBox>
31 </mx:Component>
32 </mx:itemRenderer>
33 <mx:itemEditor>
34 <mx:Component>
35 <mx:TextInput text="{data.address}" />
36 </mx:Component>
37 </mx:itemEditor>
38 </mx:DataGridColumn>
39 </mx:columns>
40 </mx:DataGrid>
41
42 <mx:Model id="custdata">
43 <customers>
44 <customer>
45 <name>Cust1</name>
46 <address>Address1</address>
47 </customer>
48 <customer>
49 <name>Cust2</name>
50 <address>Address2</address>
51 </customer>
52 <customer>
53 <name>Cust3</name>
54 <address>Address3</address>
55 </customer>
56 </customers>
57 </mx:Model>
58
59 <mx:Script>
60 <![CDATA[
61 import mx.collections.ArrayCollection;
62
63 [Bindable] private var customers:ArrayCollection = new ArrayCollection();
64
65 private function init():void {
66 customers = new ArrayCollection(custdata.customer);
67 }
68
69 public function editCell(column:Number):void {
70 myDG.editedItemPosition = {columnIndex:column, rowIndex:myDG.selectedIndex}
71 }
72 ]]>
73 </mx:Script>
74
75</mx:Application>
2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()" viewSourceURL="srcview/index.html">
3
4 <mx:DataGrid id="myDG" dataProvider="{customers}" rowCount="5" width="300" height="200" editable="true">
5 <mx:columns>
6 <mx:DataGridColumn headerText="Name" width="100" dataField="name" editable="false" editorDataField="text">
7 <mx:itemRenderer>
8 <mx:Component>
9 <mx:HBox horizontalScrollPolicy="off">
10 <mx:Label text="{data.name}" />
11 <mx:Spacer width="100%" />
12 <mx:Label text="+" click="outerDocument.editCell(0)" toolTip="Edit" />
13 </mx:HBox>
14 </mx:Component>
15 </mx:itemRenderer>
16 <mx:itemEditor>
17 <mx:Component>
18 <mx:TextInput text="{data.name}" />
19 </mx:Component>
20 </mx:itemEditor>
21 </mx:DataGridColumn>
22
23 <mx:DataGridColumn headerText="Addresss" dataField="address" width="200" editable="false" editorDataField="text">
24 <mx:itemRenderer>
25 <mx:Component>
26 <mx:HBox horizontalScrollPolicy="off">
27 <mx:Label text="{data.address}" />
28 <mx:Spacer width="100%" />
29 <mx:Label text="+" click="outerDocument.editCell(1)" toolTip="Edit" />
30 </mx:HBox>
31 </mx:Component>
32 </mx:itemRenderer>
33 <mx:itemEditor>
34 <mx:Component>
35 <mx:TextInput text="{data.address}" />
36 </mx:Component>
37 </mx:itemEditor>
38 </mx:DataGridColumn>
39 </mx:columns>
40 </mx:DataGrid>
41
42 <mx:Model id="custdata">
43 <customers>
44 <customer>
45 <name>Cust1</name>
46 <address>Address1</address>
47 </customer>
48 <customer>
49 <name>Cust2</name>
50 <address>Address2</address>
51 </customer>
52 <customer>
53 <name>Cust3</name>
54 <address>Address3</address>
55 </customer>
56 </customers>
57 </mx:Model>
58
59 <mx:Script>
60 <![CDATA[
61 import mx.collections.ArrayCollection;
62
63 [Bindable] private var customers:ArrayCollection = new ArrayCollection();
64
65 private function init():void {
66 customers = new ArrayCollection(custdata.customer);
67 }
68
69 public function editCell(column:Number):void {
70 myDG.editedItemPosition = {columnIndex:column, rowIndex:myDG.selectedIndex}
71 }
72 ]]>
73 </mx:Script>
74
75</mx:Application>
Code works in Flex 2 and Flex 3.
There's just a few thing to note:
- The datagrid needs to be marked as editable but you don't need to make the columns editable. The editable cell can set by setting the editedItemPosition property of the datagrid.
- The current row can be obtained by looking at the value of the selectedIndex property.
- You need to create an item editor as well as an item renderer and set the editorDataField for editing cells. This sets the value of the field after it has been edited.
- This example uses a "+" to indicate that a cell is editable but you could use an image instead.
Here what the code looks look when run (right click to view source and/or download):
TweetBacks
Could not resolve <mx:itemRenderer> to a component implementation.
1. adding the restrict tag to the input field.
2. giving the user info on which one is editable.
I made some changes in order to center the field values and took out the spacer.
<mx:Component>
<mx:HBox click="outerDocument.editCell(0)" horizontalAlign="center">
<mx:Label text="{data.MaxCapacity}" width="93%" paddingLeft="18" />
<mx:Label textAlign="right" text="+" toolTip="Edit" width="13" />
</mx:HBox>
</mx:Component>
Here's your dataGrid code:
<mx:DataGridColumn headerText="Quantity" dataField="Quantity" textAlign="center" itemRenderer="path.to.your.view.EditableCellRenderer"
itemEditor="path.to.your.view.EditableCellEditor" />
And here's your editable cell editor:
<?xml version="1.0" encoding="utf-8"?>
<mx:TextInput xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%"
restrict="0-9">
<mx:Script>
<![CDATA[
import mx.controls.DataGrid;
/**
* Override data setter to set cell text according to the dataField
*/
public override function set data(value:Object):void
{
var dg:DataGrid = owner as DataGrid;
text = value[dg.columns[dg.editedItemPosition.columnIndex].dataField];
}
]]>
</mx:Script>
</mx:TextInput>
This is even better since you don't need to know which order your dataGrid column is and cuts your code by like 90%.
<mx:HBoxhorizontalScrollPolicy="off">
It should be <mx:HBox horizontalScrollPolicy="off"> else you will get a compiler error.
public class EditableCellRenderer extends Label {
[Embed(source="../../common/assets/images/icon_edit_16.gif")]
private var icon_edit_16:Class;
private var img:Image;
/**
* @private
*/
private function onClickHandler(event:MouseEvent):void{
event.stopImmediatePropagation();
if(listData && listData.owner is DataGrid){
DataGrid(listData.owner).editedItemPosition =
{columnIndex:listData.columnIndex, rowIndex:DataGrid(listData.owner).selectedIndex}
}
}
/**
* @private
*/
override protected function createChildren ():void {
super.createChildren();
//mx_internal::border.visible = false;
if (!img){
img = new Image();
img.source = icon_edit_16;
img.maintainAspectRatio = true;
img.mouseFocusEnabled = false;
img.useHandCursor = true;
img.buttonMode = true;
img.mouseChildren = false;
img.toolTip = 'Edit';
img.styleName = this;
img.addEventListener(MouseEvent.CLICK,onClickHandler);
addChild(img);
}//if
}
/**
* @private
*/
override protected function measure():void {
super.measure();
measuredWidth = measuredWidth + img.getExplicitOrMeasuredWidth();
}//measure
/**
* @private
*/
override protected function updateDisplayList (unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(true){
//Image RHS
img.move((unscaledWidth - img.width), ((unscaledHeight - img.height) / 2));
} else {
//Image LHS
textField.move(img.width,0);
}//else
img.setActualSize(16, 16);
textField.setActualSize( (unscaledWidth - img.width),unscaledHeight);
}//updateDisplayList
}