My First ExtJS DataGrid Pt 4: The Data Store

So, up until now we have setup our support files and written our paging query service. Now it's time to begin tying our data to our DataGrid. The Ext library provides you many different ways of pulling in data into the components. We're going to create a data 'Store' using a combination of the HttpProxy (a utility for pulling data from within the same domain) and the XmlReader (for parsing our returned datasets).

A 'Store' is "a client side cache of Ext.data.Record objects which provide input data for widgets." Basically you create this representation of your server side data by defining where it is and what it looks like. We're using the HttpProxy, in this case, because our service script (pagingService.cfm) resides within the same domain as our calling page. And, since we set our service script to return an XML document, we need the XmlReader to 'map' the data that we need.

First we'll setup the basic block

var ds = new Ext.data.Store({

});

Add in the location of our service script

var ds = new Ext.data.Store({
    // load using HTTP
proxy: new Ext.data.HttpProxy({url: 'http://cc.mytestserver.loc/jTesting/xmlSqlTest.cfm'}),

});

Then we set up our XML 'reader'

var ds = new Ext.data.Store({
    // load using HTTP
proxy: new Ext.data.HttpProxy({url: 'http://cc.mytestserver.loc/jTesting/xmlSqlTest.cfm'}),

    // the return will be XML, so lets set up a reader
reader: new Ext.data.XmlReader({
        // records will have an "T4" tag
        record: 'T4',
        id: 'ID',
        totalRecords: "recCount"
    }, [
        // set up the fields mapping into the xml doc
        'vcFirstName', 'vcLastName', 'bIsAdministrator','bIsActive','tsDateLastLogin'
    ]),

});

Ok, here is where I have to put on the breaks for a minute. You have to understand a little about what the reader requires here. It helps if you take a look at a return recordset from your service script. I suggest you call it in Firefox for a nice representation, but basically it looks something like this:

<userList>
    <T4>
        <recCount>5802</recCount>
        <ID>2350</ID>
        <vcFirstName>Robin</vcFirstName>
        <vcLastName>Williams</vcLastName>
        <bIsAdministrator>0</bIsAdministrator>
        <bIsActive>1</bIsActive>
        <tsDateLastLogin>2007-05-01T14:34:57</tsDateLastLogin>
    </T4>
    <T4>
        <recCount>5802</recCount>
        <ID>4027</ID>
        <vcFirstName>Howie</vcFirstName>
        <vcLastName>Mandel</vcLastName>
        <bIsAdministrator>0</bIsAdministrator>
        <bIsActive>1</bIsActive>
        <tsDateLastLogin>2007-04-29T16:29:33</tsDateLastLogin>
    </T4>
    ...
</userList>

You see, looking at the XML, that each record is denoted by the 'T4' node, which we have mapped in our reader to the 'record' attribute. You'll also note that the 'id' attribute was mapped to the 'ID' node in the XML document. This is a unique identifier within each record. We mapped 'totalRecords' to the 'recCount' node, as this is where we set up in our script to place the total record count, and then you see a basic comma delimited list of the nodes that will be included in our DataGrid.

It's important to note here that we have used a very basic XML return for our example here. You do have the power to map values from XML attributes and nested nodes, through the use of XPath syntax. You can even rename a 'field' when identifying a mapping. Look through the examples included in the ExtJS download to get a better idea of what you might be able to do.

OK, to finish our DataStore definition we're going to specify the ability to 'remotely' sort our data, and set up our default sort column and sort order.

var ds = new Ext.data.Store({
    // load using HTTP
proxy: new Ext.data.HttpProxy({url: 'http://cc.mytestserver.loc/jTesting/xmlSqlTest.cfm'}),

    // the return will be XML, so lets set up a reader
reader: new Ext.data.XmlReader({
        // records will have an "T4" tag
        record: 'T4',
        id: 'ID',
        totalRecords: "recCount"
    }, [
        // set up the fields mapping into the xml doc
        'vcFirstName', 'vcLastName', 'bIsAdministrator','bIsActive','tsDateLastLogin'
    ]),
    // turn on remote sorting
    remoteSort: true
});
ds.setDefaultSort('vcLastName', 'desc');

And so begins our scripting for creating our DataGrid. The big "gotchas" that hit me along the way were the stupid things. Mis-identifying my 'record' mapping, or missing a trailing comma. Firebug and the JavaScript Console (Firefox) are your friends.

Next round we'll define our ColumnModel. This is how we'll define the order of initial column display, define column headings, and really button up the initial details before fine tuning our layout.

TweetBacks
Comments
Yash's Gravatar nice easy to understand example.
# Posted By Yash | 7/7/07 2:40 AM
help's Gravatar How about a more basic example? No pageing or joined queries....
I would love a basic example getting data from a query to xml to a datagrid in coldfusion. Extjs looks great but no help with coldfusion.
<cfquery datasource="test" name="userslist">
   select firstname,lastname,title,email
   from tblaccountsdata
   order by lastname
</cfquery>

<cfxml variable="mydoc">
<user>
<cfoutput query="userlist">
<name>
<first>#firstname#</first>
<last>#lastname#</last>
    <title>#title#</title>
    <email>#email#</email>
    </name>
</cfoutput>
</user>
</cfxml>
<cfoutput>#mydoc#</cfoutput>

How do i get this into a datagrid...New to CF please bear with me :)
# Posted By help | 7/18/07 4:18 PM
Cutter's Gravatar You don't have to do a paging grid, there are several different DataGrid examples in the ExtJS download. All you really need is a way to translate your query data into either XML or JSON. With ColdFusion 8 it is ridiculously easy, but until it's release you can always use a third party option. You should be able to find several CFCs on the web for doing these translations.
# Posted By Cutter | 7/20/07 9:50 AM
marimuthu's Gravatar Very good article. It would be great if u could add an example for nested XMl structure.
# Posted By marimuthu | 10/4/07 9:41 AM
Noel Luneau's Gravatar Hi Cutter, Great example!

Are you intending to refresh this for CF8?

And do you have an example of this file that you feference:

xmlSqlTest.cfm

Thank you,

Noel
# Posted By Noel Luneau | 12/6/07 10:05 PM
Cutter's Gravatar @Noel - I think I might have fat fingered it when I wrote the post. Check the source for the Data.Store in the included download files.

I will have some new tutorials coming soon, some dealing with the new CF8 Ajax Data features.
# Posted By Cutter | 12/7/07 6:24 AM
sathish's Gravatar By doing things specified in this article,I am only able to get the xml file.the tag values are not displayed in my grid.
I want to display the tag value..
Thanks
# Posted By sathish | 1/31/08 3:46 AM
Steve 'Cutter' Blades's Gravatar @Sathish - You know, I ran into similar issues myself, but only with IE. It had to do with data coming from one of the varchar fields. One of the records had invalid characters for XML, according to Microsoft (worked just fine in every other browser). I have since changed over all of my grid implementations to return JSON datasets instead. Much smaller data packets over the wire, easily defined, and the JSStringFormat() method around my db outputs helps keep it clean.
# Posted By Steve 'Cutter' Blades | 2/4/08 9:50 PM
Steve 'Cutter' Blades's Gravatar @Noel - No, I don't have a refresh planned soon, but only because I'm presenting on the CF8 Ajax components and Ext extension at the 2008 WebManiacs conference in DC. After that I'll have several posts refreshing these, along with some nice sample code. If you have any specific questions just let me know.
# Posted By Steve 'Cutter' Blades | 2/4/08 9:52 PM
taochenpfj's Gravatar you r so great!Anyway,i should thank u for the article!it's a great help to me!
i am a chinese!Thanks a lot!
# Posted By taochenpfj | 3/16/08 4:06 AM
aelxx's Gravatar great example, thanks
# Posted By aelxx | 4/14/08 6:49 AM
pravidya's Gravatar Is there a way to disable the column header drop down list(like sort asc, dsc, etc.? I know I can disable it by commented setting the sortable to false. But for me I still want to be able to sort but only just remove the drop down list.
The reason I want to do this is because on IE6 it does not show up properly. The drop down list appears blank.
# Posted By pravidya | 8/29/08 4:37 AM
Steve 'Cutter' Blades's Gravatar @pravidya -

I am surprised you are getting a blank list. Are the 'header' attributes set in your column model?
# Posted By Steve 'Cutter' Blades | 8/29/08 8:46 AM
Robert Kovacs's Gravatar Hi,

Is it possible to either:

maike several requests via several Ext.data.Store so that you can update the data in more than one grid?

OR

make a single request which returns json data for mor than one grid?

I have a grid of occupants and a grid of doors both of which shoul dbe updated when selecting different rooms....
# Posted By Robert Kovacs | 9/12/08 7:33 AM
Keith Howell's Gravatar Cutter,
I have searched the web and this forum extensively and cannot seem to
come up with an answer to the issue that I am having. I have a CF8
generated grid that I would like to have a mask with ... Loading show when
the grid loads and when the grid pages/refreshes. I have found many
examples of generating the grid with the extjs library but none with
a cf generated grid and then having a extjs function go back and
set the mask. I have been able to get the message to show on load, but
it does not disappear when the page finishes loading and also
does not show when paging occurs.

HELP PLEASE!
# Posted By Keith Howell | 4/29/09 6:11 PM
Steve 'Cutter' Blades's Gravatar Keith,

Setting the loading mask in the config (which you can't do in CF anyway) never worked right with Ext 1.x. If the loading mask is required, you'll want to write your grid in straight Ext 2.2.
# Posted By Steve 'Cutter' Blades | 4/29/09 7:51 PM
Keith Howell's Gravatar Cutter,
Thanks for the help. I am fairly new to extjs but have been working with
CF for about 5 years now so I think I will try your suggestion and that
should be a good way to learn it.

.. One more question though. I am using extjs to change my grid
after it has been rendered by cf (changing column names and making
some columns hidden). This seems to really slow down my application
when this code runs. Besides building the grid in extjs completely, is
there anything that I can do to speed up the "re-rendering" of the columns?
(From what I can tell, I have 55 columns in the grid and each one
is set to hidden or not and named in my ectjs function. It seems like
each time the setHidden and setColumnName functions is running
it is re-rendering the grid... so it must be running 55 times??)
# Posted By Keith Howell | 4/30/09 3:17 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.3.006. Contact Blog Owner. Layout inspired by bluerobot.com., with some JQuery thrown in for fun.