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:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()" viewSourceURL="srcview/index.html">
   
   <mx:DataGrid id="myDG" dataProvider="{customers}" rowCount="5" width="300" height="200" editable="true">
      <mx:columns>
         <mx:DataGridColumn headerText="Name" width="100" dataField="name" editable="false" editorDataField="text">
            <mx:itemRenderer>
               <mx:Component>
                  <mx:HBox>
                     <mx:Label text="{data.name}" />
                     <mx:Spacer width="100%" />
                     <mx:Label text="+" click="outerDocument.editCell(0)" toolTip="Edit" />
                  </mx:HBox>
               </mx:Component>
            </mx:itemRenderer>
            <mx:itemEditor>
               <mx:Component>
                  <mx:TextInput text="{data.name}" />
               </mx:Component>
            </mx:itemEditor>
         </mx:DataGridColumn>
         
         <mx:DataGridColumn headerText="Addresss" dataField="address" width="200" editable="false" editorDataField="text">
            <mx:itemRenderer>
               <mx:Component>
                  <mx:HBox>
                     <mx:Label text="{data.address}" />
                     <mx:Spacer width="100%" />
                     <mx:Label text="+" click="outerDocument.editCell(1)" toolTip="Edit" />
                  </mx:HBox>
               </mx:Component>
            </mx:itemRenderer>
            <mx:itemEditor>
               <mx:Component>
                  <mx:TextInput text="{data.address}" />
               </mx:Component>
            </mx:itemEditor>
         </mx:DataGridColumn>
      </mx:columns>
   </mx:DataGrid>
   
   <mx:Model id="custdata">
      <customers>
         <customer>
            <name>Cust1</name>
            <address>Address1</address>
         </customer>
         <customer>
            <name>Cust2</name>
            <address>Address2</address>
         </customer>
         <customer>
            <name>Cust3</name>
            <address>Address3</address>
         </customer>      
      </customers>
   </mx:Model>   

   <mx:Script>
      <![CDATA[
         import mx.collections.ArrayCollection;
         
         [Bindable] private var customers:ArrayCollection = new ArrayCollection();

         private function init():void {
            customers = new ArrayCollection(custdata.customer);
         }
         
         public function editCell(column:Number):void {
            myDG.editedItemPosition = {columnIndex:column, rowIndex:myDG.selectedIndex}
         }
      ]]>
   </mx:Script>

</mx:Application>

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):

Related Blog Entries

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Nuno Morgadinho's Gravatar I'm trying this in Flex Builder 3 and I get the error:

Could not resolve <mx:itemRenderer> to a component implementation.
# Posted By Nuno Morgadinho | 9/18/07 12:35 AM
Justin Mclean's Gravatar Tried it out on Flex 3 (M2 beta 1 release) and it works fine here. Have you made any changes to the code?
# Posted By Justin Mclean | 9/19/07 9:33 AM
Alex's Gravatar This is cool - but how do I add listeners to it so I know when the user has finished editing the data in a cell?
# Posted By Alex | 12/13/07 11:26 PM
brent's Gravatar Very cool. Thank you. It helps me solve two problems:

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>
# Posted By brent | 5/22/08 6:55 AM
Brent's Gravatar Yeah yeah check this out. Dig this, Johnson !! I made it better and really ObjOriented.

Here's your dataGrid code:

&lt;mx:DataGridColumn headerText=&quot;Quantity&quot; dataField=&quot;Quantity&quot; textAlign=&quot;center&quot; itemRenderer=&quot;path.to.your.view.EditableCellRenderer&quot;
itemEditor=&quot;path.to.your.view.EditableCellEditor&quot; /&gt;   

And here's your editable cell editor:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:TextInput xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
   width=&quot;100%&quot; height=&quot;100%&quot;
   restrict=&quot;0-9&quot;&gt;
   
   &lt;mx:Script&gt;
      &lt;![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];
         }
      ]]&gt;
   &lt;/mx:Script&gt;
&lt;/mx:TextInput&gt;

This is even better since you don't need to know which order your dataGrid column is and cuts your code by like 90%.
# Posted By Brent | 5/29/08 6:44 AM
Copyright © Justin Mclean 2008
BlogCFC by Raymond Camden.