How-To Update Data in an Adobe Flex DataGrid Cell using e4x | ActionScript | XML | Flash

Capturing, editing and updating data in an Adobe Flex or Flash DataGrid using ActionScript is very easy. In fact a lot easier than the most examples will show. The one important fact you need to remember about DataGrids is that they are only there to display data and to capture data. They display data that is stored in the data store, which is most cases is an ArrayCollection or XMLList.

Through the incredible sophistication of the Flex (Flash) API and its fabulous implementation of the e4x (EcmaScript for XML) standard, a developer can traverse an ArrayCollection with ease. This article demonstrates how to capture data from the grid, modify and updated it with ease and very little code.

Create a Flex Application

First create a Flex Project: UpdateDataGrid. It can be an Air or Web type application.
Next, if you are using Flex Builder 4 and later, you can add a spark skin from a template, or simply add a color of your choice. For this example I chose the theme: Arcade
Switch to the Design view and drag and drop a Panel onto the Application screen. also drag and drop a DataGrid.
Switch to the code view and change the columns to:

  • headerText:”Title”, dataField=”title”
  • headerText:”Price”, dataField=”price”
  • headerText:”Quantity”, dataField=”quantity”
  • headerText:”Total”, dataField=”total”


Make the following property changes, additions to the DataGrid in the Code view:

  • editable=”true”
  • dataProvider=”{orderArr}”
  • id=”orderGrid”
  • itemEditEnd="orderGrid_itemEditEndHandler(event)"
  • doubleClickEnabled="true"
  • doubleClick="orderGrid_doubleClickHandler(event)"


Also make the Total column non editable as we will update this column based on the values that will be entered in the Price and/or Quantity columns:

<s:Panel x="75" y="139" width="735" height="210">
		<mx:DataGrid x="44" y="0" width="640" height="155" editable="true"
					 dataProvider="{orderArr}" id="orderGrid"
					 itemEditEnd="orderGrid_itemEditEndHandler(event)"
					 doubleClickEnabled="true"
					 doubleClick="orderGrid_doubleClickHandler(event)">
			<mx:columns>
				<mx:DataGridColumn headerText="Title" dataField="title"/>
				<mx:DataGridColumn headerText="Price" dataField="price"/>
				<mx:DataGridColumn headerText="Quantity" dataField="quantity"/>
				<mx:DataGridColumn headerText="Total" dataField="total" editable="false"/>
			</mx:columns>
		</mx:DataGrid>
	</s:Panel>

You can resize the DataGrid in the Design View to taste. Next I am going to add ActionsScript 3 code in the mxml file to handle the interaction with DataGrid through the itemEditEnd event and the doubleClick event. The former will be called every time the cursor leaves the focus of a cell by tabbing or by mouse click. The latter will be called when a user double clicks on the DataGrid.

Add a Script element to the file and define a bindable ArrayCollection: orderArr.

[Bindable]
protected var orderArr:ArrayCollection;

Add init Function

Next add a protected function, init() with a void return type. In the function set the ArrayCollection and add an empty row so the user will have at least an initial empty row when launching the app. Add the function to the CreationComplete event in the application element.

protected function initApp():void
{
	//initialize the ArrayCollection
	orderArr = new ArrayCollection();
	orderArr.addItem({title:'',price:'',quantity:'',total:''});
}

Add orderGrid_itemEditEndHandler Function

Now for the bulk of the logic of our application and the main objective of this tutorial, create a protected function, orderGrid_itemEditEndHandler(event:DataGridEvent), with a DataGridEvent as a parameter. Btw, Flex Builder 4 and later will generate this for you when you add the itemEditEnd, or any other event to an element.

protected function orderGrid_itemEditEndHandler(event:DataGridEvent):void
{


}

Add Cancel Event


In our function, first check to see if the user cancels an edit and exit, return, from the function

if (event.reason == DataGridEventReason.CANCELLED)
{
// Do not update cell.
return;
}

Find Row to Edit in ArrayCollection

Next and this is important, we will need to know which row is being edited in the Adobe Flex DataGrid and also to know which row to edit in the ArrayCollection: orderArr. We will use this object, data, to access and update all our values in the mx.DataGrid

/**
* If you need to update an existing record get the row number in the grid
* and fetch the record from the ArrayCollection. It will be the same row number.
* */
				
var data:Object = orderArr.getItemAt(event.rowIndex);

Get New Value from Cell

Next I will store the new value from the cell that is being edited in a variable to be used to update our ArrayCollection and by extension our mx.DataGrid display.

/**
 * Get the new value from the editor. We will need to convert this to number for the price, 
 * quantity and total column values
 * */
			
var newVal:String = event.currentTarget.itemEditorInstance.text;

Get Original Value from Cell

I will also create a variable to the old or initial value in case the user enters a faulty value and we need to replace the original value back into the cell. Notice I am accessing two different properties of the currentarget. To get the new value, I am using the itemEditorInstance and to get the original value, I am using the editedItemRenderer property.

/**
 * Get the original value;
 * */
var oldVal:String = event.currentTarget.editedItemRenderer.data[event.dataField];

Validate Value Input

Ok, now to make sure the user only enters a valid number for the price and/or quantity columns, I will add the following code:

/**
 * Test to see if the new value is a number. If not reset to original value
* */
				
if((isNaN(new Number(newVal)) && event.dataField=='price') ||
	(isNaN(new Number(newVal)) && event.dataField=='quantity') )
				{
					Alert.show("This is not a valid number","Error");
					
					switch(event.dataField)
					{
						case 'price':
							data.price = oldVal;
							break;
						case 'quantity':
							data.quantity = oldVal;
							break;
											}
					return;
				}

First we make sure that the value is indeed a number, by attempting to convert the value to a Number and if we are editing a cell in either the price or quantity columns. If the validation fails, display a error message using Alert. Also notice how the original value is returned to the ArrayCollection. All we need to do is update the appropriate field in the ArrayCollection using the e4x syntax. This is the jest of this tutorial. In this case: data.price = oldVal and data.quantity = oldVal. No need to create any custom ItemRenderers or Editors. You just need to update the ArrayCollection once you have a handle on the row object, which we determined with: var data:Object = orderArr.getItemAt(event.rowIndex). Now we can use data and the appropriate field to update our data values.

Update DataGrid with New Value

To update the Adobe Flex mx.DataGrid, you simply obtain check if you are in the appropriate field and the value is indeed a Number and that is is greater than 0. Also you can check that the next field that is need for the update, and in our case, it is the “Quantity” field also has a value greater than 0 and even if this is a bit redundant, to check if the value is a Number. If we have the proper conditions, we only need to set the total field in the ArrayCollection at the appropriate row, like so data.total=new Number(newVal) * new Number(data.price);

if(event.dataField=='price' && new Number(newVal) > 0 && !isNaN(new Number(newVal)))
{
if((new Number(event.itemRenderer.data['quantity']) > 0 &&     !isNaN(event.itemRenderer.data['quantity'])) )
	{
	   data.total = new Number(newVal) * new Number(data.quantity);
	}
}else if(event.dataField=='quantity' && 
                   new Number(newVal) > 0 && !isNaN(new Number(newVal)))
{
            if((new Number(event.itemRenderer.data['price']) > 0 &&      
                                                          !isNaN(event.itemRenderer.data['price'])) )
            {
	        data.total = new Number(newVal) * new Number(data.price);
            }
}

Complete Function Code

protected function orderGrid_itemEditEndHandler(event:DataGridEvent):void
			{
				if (event.reason == DataGridEventReason.CANCELLED)
				{
					// Do not update cell.
					return;
				}
				/**
				 * If you need to update an existing record get the row number in the grid
				 * and fetch the record from the ArrayCollection. It will be the same row number.
				 * */
				
				var data:Object = orderArr.getItemAt(event.rowIndex);
				
				/**
				 * Get the new value from the editor. We will need to convert this to number for the price, 
				 * quantity and total column values
				 * */
			
				var newVal:String = event.currentTarget.itemEditorInstance.text;
				
				/**
				 * Get the original value
				 * */
				var oldVal:String = 
					event.currentTarget.editedItemRenderer.data[event.dataField]; 
				
				/**
				 * Test to see if the new value is a number. If not reset to original value
				 * */
				
				if((isNaN(new Number(newVal)) && event.dataField=='price') ||
					(isNaN(new Number(newVal)) && event.dataField=='quantity') ||
						(isNaN(new Number(newVal)) && event.dataField=='total'))
				{
					Alert.show("This is not a valid number","Error");
					
					switch(event.dataField)
					{
						case 'price':
							data.price = oldVal;
							break;
						case 'quantity':
							data.quantity = oldVal;
							break;
						case 'total':
							data.total = oldVal;
							break;
					}
					return;
				}
				
				if(event.dataField=='price' && new Number(newVal) > 0 && !isNaN(new Number(newVal)))
				{
					if((new Number(event.itemRenderer.data['quantity']) > 0 && !isNaN(event.itemRenderer.data['quantity'])) )
					{
						data.total = new Number(newVal) * new Number(data.quantity);
					}
				}else if(event.dataField=='quantity' && new Number(newVal) > 0 && !isNaN(new Number(newVal)))
				{
					if((new Number(event.itemRenderer.data['price']) > 0 && !isNaN(event.itemRenderer.data['price'])) )
					{
						data.total = new Number(newVal) * new Number(data.price);
					}
				}
				
				
			}

Add New Row Function

Next we need a function,orderGrid_doubleClickHandler(event:MouseEvent) , to add a new row when the user double clicks on the DataGrid.

protected function orderGrid_doubleClickHandler(event:MouseEvent):void
			{
				/**
				 * Add a new empty on double-click
				 * */
				orderArr.addItem({title:'',price:'',quantity:'',total:''});
			}

That is it. Here is a sample output, screenshot, of the application:

Hope this has been helpful. As I said at the beginning, accessing and updating a cell in a DataGrid using the underlining dataProvider and using e4x syntax to access to appropriate field.

More by this Author


Comments

No comments yet.

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working