Retrieving The Value Of A Flash DataGrid Cell

10 01 2008

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" />
	
</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.


Actions

Informations

25 responses to “Retrieving The Value Of A Flash DataGrid Cell”

31 01 2008
Bubbila (15:57:33) :

Sweet tutorial, just what I have been looking for! Well Pleased…

28 02 2008
uzo (16:13:06) :

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.

28 02 2008
Juan Wong (18:26:22) :

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?

28 02 2008
uzo (22:52:32) :

Exactly!, I want some text fields to be populated , as soon as the datagrid cells are populated.

29 02 2008
Juan Wong (11:01:03) :

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.

29 02 2008
uzo (15:48:31) :

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.

29 02 2008
Juan Wong (23:42:44) :

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.

18 03 2008
xristina (09:50:45) :

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….

18 03 2008
Juan Wong (19:35:46) :

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!

6 04 2008
Dinesh (19:03:06) :

How can I use this with Action Script 3.0?

7 04 2008
Juan Wong (13:46:49) :

Dinesh,

I haven’t tested it, but this might be of help:

Original thread
http://www.flashforum.de/forum/showthread.php?p=1749182

Translated into English

2 06 2008
Roll (06:48:03) :

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!

2 06 2008
Juan Wong (17:36:27) :

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.

12 06 2008
RL (05:15:44) :

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?

12 06 2008
Juan Wong (13:30:07) :

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

24 06 2008
Lee (14:49:20) :

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.

24 06 2008
Juan Wong (15:43:15) :

Excellent contribution, Lee!

Thanks much for sharing *thumbs up*

29 06 2008
deftones_sv (08:35:12) :

Gracias, es exactamente lo que necesito= Thanks, it’s exactly what I need

30 06 2008
Juan Wong (15:02:56) :

Me alegra haber sido de ayuda, deftones_sv :D

12 10 2008
JPH (09:10:37) :

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!

8 12 2008
Chris (06:44:51) :

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.

8 12 2008
Juan Wong (08:29:22) :

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.

24 12 2008
PJ (10:53:58) :

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

2 02 2009
Jakob (08:55:17) :

THANK YOU THANK YOU THANK YOU!

20 03 2009
Ah (17:11:52) :

Let me repeat what Jakob had to say:

\THANK YOU THANK YOU THANK YOU!\

This was a really helpful tutorial.




LiveSTRONG