Editing with a Flex Datagrid

Editing with a Datagrid
A Flex 2 Remoting Tutorial

By Renee LeBeau:

In this tutorial you can learn how to edit the information in a Flex 2 DataGrid directly.  All the examples I’ve seen online demonstrating how to edit with a DataGrid proceed by data binding TextInputs to it in a form that must be submitted.  I’ve written this tutorial so that you can see how to change the information right in the DataGrid cells.

First we will go over how to query a Microsoft Access database using a ColdFusion Component (CFC) and a Remote Object and display the results in a DataGrid.  Then we will see how to validate user changes to the information with ActionScript, and use the CFC and the Remote Object to update the Access database. Alternatively, you can use a Web Service instead of a Remote Object.

This tutorial is written for intermediate / advanced ColdFusion programmers and beginning / intermediate Flex programmers.  Before starting, you need ColdFusion MX 7.02 (or CF 8) and Flex Builder 2 installed on your local machine.

The Files

Please download this zip file: EditaDataGrid.zip
It should contain the following files: musicLibrary.mxml, retrieveMusic.cfc, and Music.mdb.

Create a new folder called MusicLibrary in the wwwroot folder of your CFMX7 installation.  Put the musicLibrary.mxml file in it, along with the Music.mdb file.  Put the retrieveMusic.cfc file straight into the wwwroot folder so that you don’t have to worry about using CFC paths.  Register Music.mdb as a Data Source in ColdFusion Administrator and call it “Music”.

Run Flex Builder 2.  Go to File -> New -> Flex Project.  Select the radio button that says “ColdFusion Flash Remoting Service”.  On the following screen select the checkbox for “Use local ColdFusion server”.  On the final screen type in “Music Library” as your project name.  Deselect the “Use default location” checkbox and Browse to the MusicLibrary folder you just created in the wwwroot.  Then click the Next button (not the Finish button).  Select musicLibrary.mxml as your “Main application file” and then click Finish.  The Music Library project should appear in your Navigator pane, and the musicLibrary.mxml file should appear in the main window.  If you select Design view you can see a single component, a DataGrid.

The Code

Querying the Access database using a CFC

Go ahead and open the retrieveMusic.cfc file provided.  You can use Dreamweaver or whatever text editor you prefer.  You can see the getLibrary method, which returns all the records from the Library table in the Microsoft Access database using a simple query called getAllCDs.  The ARTIST and CD fields are Text fields 50 characters long, and the ID field is the AutoNumber primary key.

<cffunction name="getLibrary"
	displayname="getLibrary"

	hint="Retrieves the Music Library information"
	access="remote"
	output="false"
	returntype="query">

	<cfquery name="getAllCDs" datasource="Music">
	SELECT ARTIST, CD, ID       
	FROM Library
	</cfquery>

	<cfreturn getAllCDs />
</cffunction>

In Flex Builder 2 take another look at the musicLibrary.mxml file, this time in Source view.  The DataGrid, named musicDatagrid, will hold the records called by the CFC.  To get the records into Flex, we use a Remote Object and its first method child tag.  We’ll get to the second method tag later.

<mx:RemoteObject id="LibraryQuery"
	destination="ColdFusion"
	source="retrieveMusic" 
	showBusyCursor="true" 
	fault="errorHandler(event)">
	<mx:method name="getLibrary" result="handleLibraryResult(event)" /> 

Let’s look at the different attributes for the Remote Object:

  • id - a string with the name of the component.
  • destination – the destination of the RemoteObject.  ColdFusion or Rubyamf for example.
  • source – the file name of the CFC.
  • showBusyCursor - displays the default busy cursor, a little clock, until the records finish loading into the DataGrid.
  • fault - if something goes wrong, calls the errorHandler function.

And for the first method tag:

  • name - the function in the CFC that we want to use.
  • result - how to handle the data returned by the Remote Object.

The errorHandler function simply displays an alert box with the error details:

public function errorHandler(event:FaultEvent):void {
	Alert.show(event.fault.message);                                           
}

The handleLibraryResult function assigns the results to the musicDatagrid:

public function handleLibraryResult(event:ResultEvent):void {
	musicDatagrid.dataProvider = event.result;
}

How does the Remote Object get called?  We’ll use the creationComplete attribute of the Application tag.  After the application starts and the Application form and its children are initialized, the creationComplete event takes place.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:comp="components.*" 

layout="absolute" creationComplete="initApp()">

Here we are using the creationComplete event to call the initApp function.  The initApp function calls the Remote Object:

public function initApp():void {
	LibraryQuery.getLibrary(); 
}

Why not just use the creationComplete event to call LibraryQuery?  We could, but it’s better practice to use the initApp function, in case later we decide to have more things happen at the start of the application and add more code to it.

The DataGrid

Here is our DataGrid, named musicDatagrid:

<mx:DataGrid id="musicDatagrid" editable="true" itemEditEnd="processEdit(event);" x="10" y="10">

	<mx:columns>
		<mx:DataGridColumn dataField="ARTIST" headerText="Artist Name" width="200" />
		<mx:DataGridColumn dataField="CD" headerText="CD Title" width="200" />

	</mx:columns>
</mx:DataGrid>

The DataGrid is editable. Please note that there is no DataGridColumn for the ID field, even though ID is in the query retrieved by the Remote Object and loaded into musicDataGrid.  This means that the ID field is still present and accessible, but it is invisible.

After a cell editing session ends for the ARTIST or CD fields, the itemEditEnd event occurs.  The itemEditEnd event calls the processEdit function.  But before we get to that, please note that we must declare global variables in the block of ActionScript code to hold the updated music information.  We have variables to hold the primary key, the name of the field being edited, the new value for the field being edited, and the old value for the field being edited.

[Bindable]private var keyName:int;                 // the primary key for the record
[Bindable]private var column:String;               // the field being edited
[Bindable]private var cellValue:String;            // the new value for the field being edited
private var prevCellValue:String = ';             // the old value for the field being edited

The processEdit function updates the Access database with the user’s changes, if the changes are valid. 

public function processEdit(event:DataGridEvent):void {       
   if(event.reason == DataGridEventReason.CANCELLED){    
   	return; 
   }
   
   cellValue = TextInput(event.currentTarget.itemEditorInstance).text;
   column = event.dataField;
   keyName = musicDatagrid.selectedItem.ID;                                                        
   prevCellValue = musicDatagrid.selectedItem[event.dataField];
   
   if( prevCellValue == cellValue){
   	return;
   }


   if(cellValue.length > 50) {
   	TextInput(event.currentTarget.itemEditorInstance).text = cellValue.substr(0,50);
   	event.preventDefault();
   	TextInput(musicDatagrid.itemEditorInstance).errorString="Entered text too long."; 
   	return;           
   }  
   
   updateLibraryGrid.editLibrary();
}

If the user cancelled the edit there is no need to update the data.  We also don’t need to save the data if the user typed text identical to the previous string.  If the user typed in too many characters for the field in the Access database we can trim it to the maximum allowed length, force the cell editor to stay open, and display an error message.

We use another Remote Object method, the second child tag of the same Remote Object component, to update the Microsoft Access database.  It passes the primary key, the name of the field, and the new value for the field to the CFC.


<mx:method name="editLibrary">
  	<mx:arguments>
  		<KeyName>{keyName}</KeyName>
  		<Column>{column}</Column> 
  		<CellValue>{cellValue}</CellValue>                                     
  	</mx:arguments>                               

</mx:method>
</mx:RemoteObject> 

We update the Library table by setting the field to the new value entered by the user for the record with that primary key.

<cffunction name="editLibrary" 
	displayname="editLibrary" 
	hint="Updates the information in the Music Library table" 
	access="remote" 
	output="false" 
	returntype="void">

	<cfargument name="KeyName" required="false" />
	<cfargument name="Column" required="false" />

	<cfargument name="CellValue" required="false" />
	<cfquery name="EditMusic" datasource="Music">
	update Library
	set #arguments.Column# = 
		<cfqueryparam maxlength="50" value="#arguments.CellValue#" />

	where ID =  <cfqueryparam cfsqltype="cf_sql_integer" 
		value="#arguments.KeyName#"  />
	</cfquery>
</cffunction>  

In Flex Builder, go to Project -> Build Project and then press the green Run arrow button to test for yourself how it works.  A browser window will open so you can see the DataGrid and edit the Artist and CD Title fields.  Take a look at the table in Access after editing a field in the DataGrid, and you’ll see that it’s been updated.

Flex DataGrid Image

Web Service
In ColdFusion, using Remote Object performs significantly faster than using a Web Service.  But here is how to call the CFC as a Web Service instead, in case you want to use Flex with something other than ColdFusion in your own work.  Just comment out the Remote Object tags and uncomment the Web Service tags tucked away right below it in the musicLibrary.mxml page.

<mx:WebService id="LibraryQuery"
	wsdl="http://localhost:8500/retrieveMusic.cfc?wsdl" 
	showBusyCursor="true">

    
	<mx:operation name="getLibrary" 
		result="handleLibraryResult(event)"
		fault="errorHandler(event)"/>

	<mx:operation name="editLibrary">

		<mx:request>
			<KeyName>{keyName}</KeyName>
			<Column>{column}</Column> 
			<CellValue>{cellValue}</CellValue> 
		</mx:request> 
	</mx:operation>

</mx:WebService>

The wsdl property must indicate the location of the WSDL document for the Web Service.

Conclusion
I hope this tutorial proves useful to you, and that you are able to update information in DataGrids of your own design directly now.  I appreciate feedback.  You can reach me by e-mail at:


Links



All ColdFusion Tutorials By Author: Renee
  • Editing with a Flex Datagrid
    Would you like to learn how to edit the information in a Flex 2 DataGrid directly? All the examples I’ve seen proceed by data binding TextInputs to a DataGrid as part of a form. I’ve written this tutorial so that you can change the information right in the DataGrid cells.
    Author: Renee
    Views: 3,263
    Posted Date: Thursday, February 21, 2008