Retrieving the new values while editing data inside the Data Grids
Maybe you like data grids as much as I do, or maybe you don’t like them at all. But either way, you decide one day that you want to use a data grid not only for displaying the data, but also for editing the data inline.
How do you do that? Or to rephrase the question, how do you get the new value once the user has finished editing one cell? If you search on the Internet, you will find different ways to do this. But somehow, they all seem to be less straightforward than you would expect.
I mean, when I first started to implement this behavior for an project I was working on, I expected to find an event that is dispatched by the data grid once the editing was finished. And using that event, I would access the old values and the new values. If you ever worked with triggers in a relational database, you probably remember that inside of a trigger you can easily access the old row and the new row values (that is, the values before the update and after). Well, it turns out that with a Flex data grid things are not as straightforward as I expected.
First I started by looking at the events that a data grid can dispatch. From that long list, only the events involving item_and_something looked like they would satisfy my needs. And out of that, I pick the event itemEditEnd as the lucky winner. Now, if you register an event listener on this event and then you go in debug mode and inspect the event, you will find that the data property is still not updated. Instead, you will find the old value and there is no property such as newValue or something similar to easily get the new value. At the time when this event is dispatched, the data model used by the data grid isn’t updated.
The only way I found to get the new data is to do something like this:
private function editListener(eventataGridEvent):void { //get the data grid component var dataGrid:DataGrid = event.target as DataGrid; //get the column object var col:DataGridColumn = dataGrid.columns[event.columnIndex]; //use the column object and data grid itemEditorInstance property to retrieve the new value var newValue:String = dataGrid.itemEditorInstance[col.editorDataField]; //get the old value var oldValue:String = event.itemRenderer.data.toString(); }
While this code isn’t complicated, it’s not simple either. This leaves me with two questions:
- If you ever edited inline of a data grid, how did you do it?
- Why doesn’t the data grid have an event that just offers the old and new value when one cell is edited? I’ve just submitted a feature request for the Flex SDK for this one: https://bugs.adobe.com/jira/browse/SDK-16680 If you have the time, maybe you can vote for it.
Here is a small project sample to try the code.
UPDATE
A friend poited me out, that Peter Ent wrote about this too: http://weblogs.macromedia.com/pent/archives/2008/06/itemeditors_-_p_1.html
360|Flex and AMP
If you haven’t the chance to participate in a 360|Flex conference, you can watch 15 sessions from one event using AMP (Adobe Media Player). It is very simple:
- Install AMP
- Click “My Favorites” menu at the top.
- Click “Add RSS Feed” at the bottom.
- Paste: http://sessions.onflex.org/1733261879.xml
Enjoy!
Do you want a ticket to "Flash on the Beach" for free?
Between 28th September – 1st October it will be the Flash on the Beach conference in Brighton, UK. This is the third edition and it is a conference that you shouldn’t skip. Now, you have the chance to win a free ticket (a £499/€633 value). You have to send us a photo that is with you, and has a beach theme, and shows the love for Flash/Flex/AIR. And we will choose the winners – because we have 6 tickets to give it away!
Serje Jespers is collecting the photos via his blog. And each one of the six European platform evangelists will choose one winner: Andrew Shorten, Enrique Duvos, Serje Jespers, Cornel Creanga, myself and Mihai Pricope. We will announce the winners starting with 8th September.
Good luck people, and start making photos if you don’t have!
Paging a Data Grid on the client
My wife says that lately I have become obsessed, with data grids. Well, who am I kidding? While my wife is a psychologist and she does care about obsessions, she doesn’t care about Flex components. Anyway, the first time I saw a Flex data grid filled with items I asked myself: “What if I need to display more than 20 rows of data at the same time?” What visual hints, what UI should I use, to give the viewer a sense of what items he is looking at, how many there are left to see, and so on. Let’s take a look at it; here’s a data grid filled with a lot of data:
When I was a web developer with InterAKT Online, I worked on a product called NeXTensio list. This product was an extension for Dreamweaver, and it was used for generating lists from a table or from a query, and it provided navigation buttons and other visual items to help you view and edit the list items.
So, it is no wonder that, as soon I had some time to play, I started to build a Flex component that adds some interesting behavior to a data grid. You can see here the whole thing put it together, and you can download the project from here (in the root of the ZIP file there is a readme.txt file that explains how to setup the project). About my application:
- using a HTTPService, it reads all the data from the database; my example uses a MySQL table with 5.000 rows
- it displays the data using a data grid
- users navigate through the data grid using my custom component; the component adds buttons for navigating from page to page (where a page is the number of items you can view at the same time in the data grid), or you can directly navigate to the last/first page
- my custom component display some statistics on top of the navigation buttons (so you know what dataset are you looking at, and how many items there are)
- you can use the data grid toolbar, and in this case as you move around, the buttons and statistics are updated (just use the mouse or the keyboard to scroll the data grid, and you will see the buttons changing)
Here is a screen shot of the application:
How did I do it? Well, it wasn’t hard, but neither was it easy. The whole paging component is a custom Flex component (see the Paging.mxml file). All it needs is a reference to the data grid to which you want to add paging. You can configure how many buttons to render at the same time for moving through pages (I used 5 in my example). The trickiest part was to find how many items are displayed at one time in the data grid. When a data grid is initialized, the property rowCount from the data grid is 7, regardless of how many items are in the data grid. So, I need to have a listener registered on the data grid that it is triggered when rowCount changes. Because I couldn’t find an event for this, I ended up extending the data grid (see the MyDataGrid.mxml file) and I over-wrote the method setRowCount, to dispatch an event when rowCount changes.
For the rest of the story, have a look at the code and play with it. But please, don’t forget it isn’t production quality code, it’s just a proof of concept. Have fun!
LiveCycle Data Services 2.6 – new features
As you probably know, LCDS 2.6 was released last month. If you are not sure what new features it brings, or you want a more detailed description of them, you can look to my friend, Cornel Creanga, Blog posts here and here.
"30onMAX" or how to be in the MAX Keynote
If you want to be in the MAX Keynote, keep reading:) Adobe is putting together a video project of your videos called “30onMAX”. The selected videos will be used in MAX Keynote in San Francisco, Milan and Tokyo. To get there, you need to create a video on Why MAX?, upload the video on Youtube.com and tag it with “30onMAX”.
Duane’s World Episode 8
My friend Duane Nickull, (if you don’t know him, take a look at his blog), released episode 8 of his show. In this episode, you can watch interviews with Tim O’Reilly, John Markoff, Dries Buytaert and Bob Glushko.
Functional Testing Framework for AIR AJAX apps based on Selenium
My friends from the Romanian Adobe AIR team have been very busy lately. Marius and Alex have been working on, was to modifying Selenium so you can run automated / functional tests on AIR applications developed with HTML/JS.
To be honest, I am quite amazed about what they managed to pull off in so little time. And because we need your feedback, I have an archive ready for download here, so you can start playing with it in minutes. Here is what it is in ZIP:
- demo movies – two movies that show you the workflow supported for now
- sample tests – this is the interesting part. You have two applications and some tests files to test these applications with this framework. The first test uses a Selenium based model for dispatching UI events, the second uses a Java AWT robot to generate mouse and key events.
- selenium recorder – this lets you record your UI interaction with the application. Then with a little editing on the resulting test files you can create the test cases for your automated testing.
- selenium server – this is the heart of this framework. It acts as a proxy between the requests that are made from tests and the AIR application.
- readme.txt – for a quick start on trying the samples; this files describes how to create a Java project and run the tests from Eclipse as a JUnit Test Case.
- SeleniumWithAIR.pdf – the first draft of documentation for this framework, which includes the known issues.
It should work on Win and Mac, with Java 1.5 or newer and AIR SDK 1.1.
Here is a short explanation of how to quickly run the tests from the ZIP file:
- Download the ZIP, and unzip somewhere on your disk
- Create a system variable named ADL_EXE and set its value to the full path of the “adl” executable from your local AIR SDK

- Start the server: selenium/selenium server/runServer.bat

- Run the tests: selenium/sample tests/runTest.bat


Here is a snapshot of the Eclipse project to run the tests from the ZIP:
So, that’s it! Try these goodies and let me know what you think!
Extending ActionScript classes to provide AsyncToken like behavior
When you use a class from the Flex framework that does an asynchronous call, you can use the AsyncToken that the call returns to save values/objects that you need when the result event is triggered.
Let’s look at this code:
private function getData():void { //create a new HTTPService var myService = new HTTPService(); //add event listener for result myService.addEventListener(ResultEvent.RESULT, resultListener); //save the async token var token:AsyncToken = myService.send(); //add to token our own data token.myData = {name: "john doe", id : 1}; } private function resultListener(event:ResultEvent):void { //retrieve from event.token our data myData:Object = event.token.myData; }
So, we have two functions. The first, getData() creates a HTTPService, attaches an event listener for the result event, and then makes a call to the server. When it makes a call, an AsyncToken is returned. I can use this token to store some info I need in the result listener. The second function is the definition of the result listener. When this function is called, you can access the AsyncToken from the property token from event: event.token. Having the token, it is easy to retrieve the data that I stored when I made the call to the service.
Why is that useful? Sometimes you want to be able to associated some data to a particular call, so when result event is called, you are able to take a different actions based on the data passed.
Unfortunately, when you do a call to a class from Flash, for example, flash.net.URLLoader you don’t have this AsyncToken returned. Consider the following code:
var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, completeListener); //this line does not working; the load() method is not returning anything var token = loader.load(new URLRequest("http://mysite/pic.png));
How do you pass your data between the call and the result for objects that are not using AsyncToken? One simple way is to extend the object you want to use, and add one property to store an object. Let’s do this for the URLLoader class:
public class MyLoader extends URLLoader { private var _data:Object; public function MyLoader(data:Object) { super(); this._data = data; } public function get data():Object { return this._data; } }
Now, let’s see how you can use this object to do asynchronous calls and still be able to pass data:
var myData:Object = {name : "john doe", id : 9}; var loader:MyLoader = new MyLoader(myData); loader.addEventListener(Event.COMPLETE, completeListener); //make a request for an item from server loader.load(new URLRequest("http://myste/pic.png)); //complete listener for loader private function completeListener(event:Event):void { //retrieve the loader instance var myLoader:MyLoader = event.target; //retrieve the data object var myData:Object = myLoader.data; }
When I create the custom loader object, I pass a reference to the data object that I want to retrieve when the loader has the response (this object is stored using the _data property from MyLoader). When the complete event is reached, using the target property on the event object, I retrieve the MyLoader object that made the call . Having the loader object, I can access the data property to retrieve the original data I stored.
ScaleNine "Skin to Win Challenge" – contest for Flex themes
If you know how to skin Flex apps, and you need one of these: Macbook AIR with SSD, Creative Suite 3, Flex Builder Professional or a ticket to MAX 2008, just go here and submit your best themes for Flex, and you might win!


