Flex DataGrid – Data updates not reflected

Standard
Spread the love

Flex datagrid is nice option to display data in tabular format and with built-in features like sort, rearrange column position and customize each columns with renderers/editors, it makes developers life easy to built user friendly application in quick time.  But most of the time, those who have coded in Flex, must have noticed that the datagrid just doesnt work properly when row information is updated. Consider following scenario.

1. Datagrid uses ItemEditor to update Collection bound as dataprovider.
2. A change in value of one of the column, involves updates to values displayed in other columns.

In 2nd step, user may change value in one of the column, which will internally result in change in value displayed in other columns. One can easily achieve that using itemEditEnd event but most of the time the updates are not reflected. Consider following code


		
			
			
			
			
			
			
		
	
	
	
		
			
			
			
			
				
				
				
				
			
		
	


Above code just binds one ArrayCollection to datagrid and editable values are displayed in textboxes. The basic requirement is that whenever user enters “Gross” and “Commission %”, the “Commission” and “Net” column should be updated. The logic to achieve this is defined in following function

private function calculateCommission(evt:AdvancedDataGridEvent):void
{
	if(evt.reason == DataGridEventReason.CANCELLED)
		return;
	var dtIndex:int = evt.currentTarget.selectedIndex;
	var dtField:String = evt.dataField;
			
	var gross:*, commPer:*, comm:*, net:*;
	var dataGross:* = evt.itemRenderer.data.gross;
	var dataCommPer:* = evt.itemRenderer.data.commPer;
	var dataComm:* = evt.itemRenderer.data.comm;
	var dataNet:* = evt.itemRenderer.data.net;
	switch(dtField)
	{
		case "gross":
			trace("gross column edited.");
			gross = evt.currentTarget.itemEditorInstance.text;
			if( (dataCommPer != null) && (dataCommPer!="") )
			{
				comm = (gross * dataCommPer) / 100;
				net = gross - comm;
			}else if( (dataComm != null) && (dataComm!=""))
			{
				commPer = (dataComm * 100) / gross;
				net = gross - dataComm;
			}else{
				net = gross;
			}
			break;
		case "commPer":
			trace("comm % column edited.");
			commPer = evt.currentTarget.itemEditorInstance.text;
			if( (dataGross != null) && (dataGross!="") )
			{
				comm = dataGross * (commPer / 100);
				net = dataGross - comm;
			}
			break;
		case "comm":
			trace("comm column edited.");
			comm = evt.currentTarget.itemEditorInstance.text;
			if( (dataGross != null) && (dataGross!="") )
			{
				commPer = (100 * comm) / dataGross;
				net = dataGross - comm;
			}
			break;
		case "net":
			trace("net column edited.");
			net = evt.currentTarget.itemEditorInstance.text;
			break;
		}
				
		var item:Object = evt.currentTarget.dataProvider.getItemAt(dtIndex);
		
		if(gross!=null)
			item.gross = gross;
		if(commPer!=null)
			item.commPer = commPer;
		if(comm!=null)
			item.comm = comm;
		if(net!=null)
			item.net = net;
		evt.currentTarget.dataProvider.itemUpdated(item);
		}

(Note that above code is not completed but used for illustration purpose). Above code updates values in respective properties of given item and invokes itemUpdated function on underlying ArrayCollection. If you run the application, you might notice that the application behaves unexpectadly. Sometimes the values are updated and sometimes it wont update value. To resolve this issue, comment “itemUpdated” function call and add following code.

var colEvent:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE,
true,false, CollectionEventKind.UPDATE);
colEvent.items = [item];
colEvent.location =  dtIndex;
(evt.currentTarget.dataProvider as ArrayCollection).dispatchEvent(colEvent);

You will now notice that everytime you update the column values, the changes are reflected properly. Above code will work in all scenarios, except one. To simulate that issue, perform following steps

1. Enter some values in all the rows.
2. Click on textbox displayed for “Commission” column of 1st row.
3. Without changing any value, now select “Gross” column textbox of 2nd row with left button of mouse.
4. Change the value displayed in “Gross” textbox of 2nd row and tab out. You will notice that tab will focus on 1st row rather than moving to next textbox.

The reason behind such unexpected behavior is that when user directly selects the value in any of the editable column, the datagrid controls is not able to track the event and hence the itemEditedPosition property is not set.
To make above code work, you should modify the itemRenderer attribute in above code and create one mxml renderer component. Refer to following code.


	
			

I would name this file as “AmountInput.mxml” and change itemRenderer Attribute of the datagridcolumn to point this new component.
Build the project and run it. Now you would notice that the data updations are reflected properly.

Hope this helps !

Updated : Thought of putting source code for this example, to download the source code just click here. I am using Flex SDK 3.4 with target flash player version as 10.0.0.

6 thoughts on “Flex DataGrid – Data updates not reflected

  1. Alicia

    Hi, Carbon Rider,
    Thanks for the helpful article. If your ArrayCollection was hierarchical so that each object had its own ArrayCollection, is there a way from the AdvancedDataGridEvent to tell which child was changed? The “event.currentTarget.selectedIndex” gives me the parent object.

    Thanks for your help!
    Alicia

    • Hi Alicia,

      To get the child object that has changed, you can make use of “event.itemRenderer.data” – This will return an object instance of the child which was modified.
      I have created one sample Flex application, which you can download here. The duration column is marked as editable and hence once you will expand any of the student
      node & edit the duration, you will find trace for the edited item. Note that the data on console emits information before change.

  2. Hi, thanks for tutorial, its very helfull.
    What necessary change if i want to put Quantity(qty) column?
    gross*qty and the result like gross in this tutorial.
    Thankyou.

  3. Nafri

    yes that should work,but i also need that columns (commission and comm %). My dg column headers : Product,Company,gross,qty,comm%,comm(hidden),net

  4. GK

    Nice Article. I am facing small issue with it though – This is error
    TypeError: Error #1010: A term is undefined and has no properties.
    at mx.controls::AdvancedDataGridBaseEx/commitEditedItemPosition()
    at mx.controls::AdvancedDataGridBaseEx/updateDisplayList()
    at mx.controls::AdvancedDataGrid/updateDisplayList()
    at mx.controls.listClasses::AdvancedListBase/validateDisplayList()
    at mx.managers::LayoutManager/validateDisplayList()
    at mx.managers::LayoutManager/doPhasedInstantiation()
    at mx.managers::LayoutManager/doPhasedInstantiationCallback()

    When I try and edit an editable column it is give me proper row & column idx but throwing this error.

Leave a Reply

Your email address will not be published. Required fields are marked *