Retrieving The Value Of A Flash DataGrid Cell

Well, kinda late, but I wish you all a Happy New Year!

This year, I want to blog more. And to accomplish this, I’ll be managing my time better. It won’t be easy but I’ll do it.

Okay, now on to today’s tip.

Because I’m kinda rusty in ActionScript, one of my goals is to develop more Flash applications.

Anyway, here I’ll give you a very simple example on how you can retrieve the value of a Flash DataGrid cell. I had to do something like this at my job, and I had to spend quite some time doing some research to figure this out. This tip, hopefully, will save you some time.

Ah! I’m assuming you already have some flash/actionscript experience, so I’ll keep this as short as possible.

Let’s say we have an XML file with movie titles that we want to populate to a Flash DataGrid.

< ?xml version="1.0" encoding="UTF-8"?>
<movies>
	<movie name="Transformers" year="2007" genre="Action" />
	<movie name="Pan's Labyrinth" year="2006" genre="Fantasy" />
	<movie name="The Commitments" year="1991" genre="Comedy" />
	<movie name="1408" year="2007" genre="Horror" />
	<movie name="Hero" year="2004" genre="Action" />
	<movie name="Braveheart" year="1995" genre="Epic" />
	<movie name="House of Flying Daggers" year="2004" genre="Action" />
</movies>

Now, let’s create the DataGrid (this tip works in Flash8 and CS3);

Open Flash and create two layers: actions (lock it) and dataGrid.

Layers

Now, from your components window, drag the DataGrid component into the stage and let’s name its instance “dgMovies”.

DataGrid Component

Properties

That’s it. Now, let’s write some ActionScript!

If we want to retrieve the value of a specific row cell of a specific column no matter where in the row we click, like for instance we want to retrieve the cell values of the Genre column, like this:

(this is not an image)

Then, the ActionScript to accomplish this is:

var mXML:XML = new XML();
 
mXML.ignoreWhite = true;
 
mXML.onLoad = function(){
	if(mXML.loaded){
		//create array that will hold the movies info
		var arrMovies:Array = this.firstChild.childNodes;
		var i:Number = 0;
 
		for(i; i < arrMovies.length; i++){
                       //Let's retrieve the values of the attributes and store them in variables
			var movieName:String = arrMovies[i].attributes.name;
			var movieYear:Number = arrMovies[i].attributes.year;
			var movieGenre:String = arrMovies[i].attributes.genre;
 
			//Let's create an associative array using an Object constructor
			//this array will be used to populate our DataGrid
			var item:Object = {Name:movieName, Year:movieYear, Genre:movieGenre};
 
			//Let's set our columns widths
			dgMovies.getColumnAt(0).width = 250;
			dgMovies.getColumnAt(1).width = 50;
			dgMovies.getColumnAt(2).width = 150;
 
			dgMovies.getColumnAt(0).resizable = false;
			dgMovies.getColumnAt(1).resizable = false;
			dgMovies.getColumnAt(2).resizable = false;
 
			dgMovies.addItem(item);
 
		}
 
		//let's create the event listener to our DataGrid object
		var dgListener:Object = new Object();
 
		dgListener.cellPress = function(eObj:Object) {						
 
			//to retrieve cell values in the "Genre" column
			var cellVal:Object = eObj.target.selectedItem.Genre;
 
			dtxtOutput.text = cellVal.toString();
 
		};
 
		//let's add the event listener to our DataGrid object
		dgMovies.addEventListener("cellPress", dgListener);
 
 
	}
}
 
mXML.load("movies.xml");

OK, in this line eObj.target.selectedItem.Genre; I could’ve use the array access syntax instead (eObj.target.selectedItem["Genre"];), but in this case using the dot operator is fine since we only want the cell values of one column.

But what if we want to retrieve the value of every cell we click on, like this?

(this is not an image, click on any cell)

Well, we just need to add a couple of more lines to our AS code. We do this in the anonymous function() of the cellPress event:

dgListener.cellPress = function(eObj:Object) {
 
	//let's retrieve column name
	var colName:Object = eObj.target.columns[eObj.columnIndex].columnName;
 
	//to retrieve cell value
	var cellVal:Object = eObj.target.selectedItem[colName];
 
	dtxtOutput.text = cellVal.toString();
 
};

As you can see in this line eObj.target.selectedItem[colName];, I'm using the array access syntax because the column name is being called dynamically (eObj.target.columns[eObj.columnIndex].columnName;); thus, we need to put it in a variable. Of course, the dot operator wouldn't work here.

So, your modified ActionScript should look something like this:

var mXML:XML = new XML();
 
mXML.ignoreWhite = true;
 
mXML.onLoad = function(){
	if(mXML.loaded){
		//create array that will hold the movies info
		var arrMovies:Array = this.firstChild.childNodes;
		var i:Number = 0;
 
		for(i; i < arrMovies.length; i++){
			var movieName:String = arrMovies[i].attributes.name;
			var movieYear:Number = arrMovies[i].attributes.year;
			var movieGenre:String = arrMovies[i].attributes.genre;
 
			//Let's create an associative array using an Object constructor
			//this array will be used to populate our DataGrid
			var item:Object = {Name:movieName, Year:movieYear, Genre:movieGenre};
 
			//Let's set out columns widths
			dgMovies.getColumnAt(0).width = 250;
			dgMovies.getColumnAt(1).width = 50;
			dgMovies.getColumnAt(2).width = 150;
 
			dgMovies.getColumnAt(0).resizable = false;
			dgMovies.getColumnAt(1).resizable = false;
			dgMovies.getColumnAt(2).resizable = false;
 
			dgMovies.addItem(item);
 
		}
 
		//let's create the event listener to our DataGrid object
		var dgListener:Object = new Object();
 
		dgListener.cellPress = function(eObj:Object) {
 
			//let's retrieve column name
			var colName:Object = eObj.target.columns[eObj.columnIndex].columnName;
 
			//to retrieve cell value
			var cellVal:Object = eObj.target.selectedItem[colName];
 
			dtxtOutput.text = cellVal.toString();
 
		};
 
		//let's add the event listener to our DataGrid object
		dgMovies.addEventListener("cellPress", dgListener);
 
 
	}
}
 
mXML.load("movies.xml");

That's it!

Like I said, this is a very basic, very simple example on how you can retrieve the values of a Flash DataGrid cell. You can take it from there.

If there's a more efficient way to do this, by all means, don't be shy and let me know.

Hope this helps.

25 thoughts on “Retrieving The Value Of A Flash DataGrid Cell

  1. uzo

    Thanks for this great tut. But please i used my datagrid component to retrieve
    a recordset from my database via flash remoting. Now i’d like to retrieve the value of each data grid cell into a textfield automatically (without pressing a cell- cellPress to retrieve the value). The following line may be awkward but its the best way to describe what i need :
    var myData = myDataGrid.child.child.cellValue;
    myTextField_txt.text = myData.toString();

    Please help.

  2. Juan Wong Post author

    okay, so just to make sure I understand what you want; as soon as the datagrid cells are populated with data, you want some text fields to be populated as well?

  3. Juan Wong Post author

    Uzo,

    Try this:

    Generate a dynamic textfield in the loop where you’re populating your datagrid cells. If I was to do this on my example above, I’d do it like this:

    var tfName:String = "txtField" + i;
    		
    _root.createTextField(tfName, _root.getNextHighestDepth(), 20, (i * 25) + 200, 50, 30);
    _root[tfName].text = movieName;
    trace(_root[tfName].text);
    

    That would generate as many text fields as there are movies in my .xml file and each text field would be automatically populated with the name of the movies.

    If you’re wondering what does this mean: (i * 25) + 200; well, here I’m adding 200 units to the _y property so that the text fields will be displayed below the datagrid.

    I hope this points you to the right direction.

  4. uzo

    Juan Wong,
    thanks, it worked well with your example when i tried it, but i still can’t use it to retrieve data from my datagrid (messageDisplay). This is what my code looks like:

    /*——————————
    Remote Connection
    ——————————-*/
    import mx.remoting.Service;
    import mx.services.Log;
    import mx.rpc.RelayResponder;
    import mx.rpc.FaultEvent;
    import mx.rpc.ResultEvent;
    import mx.remoting.PendingCall;
    import mx.remoting.RecordSet;

    // connect to service and create service object

    var sportService:Service = new Service(“http://localhost/flashservices/gateway”, null(), “intersport.players_query”, null, null);

    // call the service getCurrency() method
    var pc:PendingCall = sportService.getCurrency();

    // tell the service what methods handle result and fault conditions
    pc.responder = new RelayResponder(this, “getCurrency_Result”, “getCurrency_Fault”);
    function getCurrency_Result(result:ResultEvent) {

    // display successful result
    messageDisplay.dataProvider = result.result;
    }
    function getCurrency_Fault(fault:FaultEvent) {

    //display fault returned from service
    messageDisplay.dataProvider = fault.fault.faultstring;

    }

    once the connection is successful my empty datagrid (messageDisplay) is populated with the data from my database. I think it is converted to an Array (not XML ) in my datagrid.

  5. Juan Wong Post author

    Uzo,

    Yes, the data is ‘converted’ to an array. So, since you’re not using a loop to populate your DG, what you’d need to do is to put such data into a ‘real’ array so that you can retrieve those values at once and populate your text fields.

    Try this:

    //create an array from your datagrid
    var arrDataGrid:Array = messageDisplay.dataProvider;
    
    //now write a for() loop to populate it with the datagrid data
    for(i = 0; i < arrDataGrid.length; i++){
    
           //create the variable name for the text fields (like in my first suggestion)
    	var tfName:String = "txtField" + i;
    	_root.createTextField(tfName, _root.getNextHighestDepth(), 20, (i * 25) + 200, 50, 30);
    
            //now populate the textfields with the data of the cell you want.
    	_root[tfName].text = arrDataGrid[i].YourColumnName;
    	trace(_root[tfName].text);
    }
    

    The "YourColumnName" is, of course, the name of the column (header) whose cell values you want to populate your text fields with.

    I hope this helps and points you to the right direction.

    If you have more questions, please be advised that it will take some time for me to reply since I won't be available until Sunday evening.

  6. xristina

    hello..congratulations for the tutorial…but i would like to ask something more….how can i show the hand pointer on each datagrid cell???
    please help me if you can….i tried the following actioscript code:
    datagrid_name.useHandCursor = true;
    i didn ‘ t see any result….
    thank you for your answer….

  7. Juan Wong Post author

    Hello Xristina,

    Thanks for your comment. I’m gonna look into that and I’ll post the answer here as soon as I have it.

    Best!

  8. Roll

    hello and thanks for your tutorial, but does this code work in AS3? And if not, would you mind to publish a way to get an item like you did, but in AS3? Thank you again!

  9. Juan Wong Post author

    Roll,

    This works using AS2. To make it work with AS3, I’d suggest you using the link I put above your post.

    I’m planning to make a tutorial on how to make this work using AS3, but unfortunately, I have too much on my plate right now. I’ll be able to do it but until I finish other projects I’m working on.

  10. RL

    Is there a way of adding a hyperlink to each cell, so instead of it writing a text box below the datagrid, it takes you to a new page?

  11. Juan Wong Post author

    RL,

    You could add one more attribute to your .xml file so, based on my example, it would read something like this:

    <movie name="Transformers" year="2007" genre="Action" link="[movieURL]" />
    

    Then, in the AS for() loop, you would add one more variable to hold the URL:

    var movieURL:String = arrMovies[i].attributes.link;
    

    Also, you’d need to add the new variable to the item object so that it reads like so:

    var item:Object = {Name:movieName, Year:movieYear, Genre:movieGenre, mURL:movieURL};
    

    Then, in the cellPress event listener you would add the following code (this would take the user to a different page every time they click on the movie title):

    if(eObj.columnIndex == 0){
    	var siteURL:Object = eObj.target.selectedItem.mURL;
    	getURL(siteURL.toString());
    }
    

    HTH

  12. Lee

    Great code–you inspired a breakthrough in my AS3 project.

    Here’s how I adapted this code to AS3:

    So you’ve got your dataProvider all set up, everything’s loaded into the grid. I’m loading my stuff from an array (it’s part of an RSS Reader–XML Published Date, Title, Description have all been passed into an array) and I want the DataGrid to only show the Published Date and Title, and then the Description will appear in as HTML Text Label below.

    Here’s how to get the Label to be the HTMLText of your selected item once in the grid:

    description_lbl.htmlText = event.target.selectedItem.desc;

    (the “desc” at the end of event.target.selectedItem is how I labeled the description data parsed into the array).

    This is a bit of a hack, since the DataGrid wants to show the Description along with the Title and PubDate, so I limit it when I draw the DataGrid:

    my_dg.columns = ["date", "title"];

    Again, “date” and “title” are the label’s I’ve passed onto the array.

    Hope this helps.

  13. JPH

    Wow, man. I’ve been trying to accomplish this for hours. When you hit a wall like this it tends to make you a bit frustrated to say the least.

    Anyway thanks a million for this!

  14. Chris

    I’ve been trying to figure out how to make something like this but that takes the numerical value of two cells in a column and writes the sum of the two numbers into a new row. Is anything like that possible? Like a score tabulating application.

  15. Juan Wong Post author

    Chris,

    I’m sure there’s a way. Have you tried putting the values in a variable in the loop?

    I’d need to make some tests meself. Let me try that and I’ll be posting here as soon as I have something.

  16. PJ

    Thanks! You gave me a missing element to a feature I was building. I couldn’t find the documenation I needed on some of the DataGrid properties… Adobe should put emamples like this in their Doc’s. thx ~ pj

  17. Ah

    Let me repeat what Jakob had to say:

    \THANK YOU THANK YOU THANK YOU!\

    This was a really helpful tutorial.

Comments are closed.