The ExtJs editable grid in a nutshell – part 1 setting up your grid.

One of the biggest problems I faced when developing a good editable grid is the ability to properly populate the dynamic drop-down boxes within the table. ExtJS performs this task much better than most of the packages that I have worked with so far. The following will walk you through and explain an editable grid that has been created using MySQL, PHP and ExtJS. In order to replicate the program you will have to create a table that holds the options, so open MySQL and run the following script (assumes that a database named ‘test’ has been created:

CREATE  TABLE IF NOT EXISTS `test`.`some_options` (
`so_pk_id` INT NOT NULL ,
`option_name` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`so_pk_id`) )
ENGINE = MyISAM;

Insert into test.some_options (so_pk_id,option_name) values ('1','Red')
Insert into test.some_options (so_pk_id,option_name) values ('2','Yellow')
Insert into test.some_options (so_pk_id,option_name) values ('3','Green')

Now we need some fake data for out table, so let’s create the following which will be the table that we will be editing via our editable grid.

CREATE  TABLE `test`.`light_test` (
  `pk_light_id` INT NOT NULL ,
  `color` INT NULL ,
  `name` VARCHAR(45) NULL ,
  `location` VARCHAR(45) NULL );

Insert into test.light_test (pk_light_id,color,name,location) values ('1','2','Some Light','Around the corner')

Ok now that we have the tables set up we will need to create a few pages that will fetch the data from our database and place them into what Ext calls stores, these data stores will contain the original values.

First we will need to connect to the ‘some_options’ table that was created above and get all of the data from the table into a nice JSON string. Fortunately, this is much easier than it sounds when using PHP since there is a handy function called json_encode() that returns the query results in a JSON string, so the code to do this is as follows:

<?php
// The source code of optionsstire.php
$dbhost = '127.0.0.1:3306';
$dbuser = 'test_user';
$dbpass = '';

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die  ('Error connecting to mysql');

$dbname = 'test';
mysql_select_db($dbname);

$query = "select * from some_options";

 
$result = mysql_query($query);
$num = mysql_numrows($result);
$options = array("results" => $num);
$i = 0;
  while ($row = mysql_fetch_assoc($result)) {
    $options["data"][$i] = $row;
    $i++;
  }
  echo json_encode($options);
?>

…. and of course we need the same code for the main data grid store, which in reality is as simple as changing the line $query = “select * from some_options”; to $query = “select * from light_test”; ..

Now that the foundation has been put in place let’s move on to those stores that were mentioned above. In order to get data into your drop down box, or data grid you will need to connect the data in the lookup table that is in the database with the drop down or combo box. The code for a simple JSON store that matches the PHP code above is:

var option_dd_store = new Ext.data.JsonStore({
            storeId:'option_dd_store',
            autoLoad: true,
            url:'optionsstore.php',
            idProperty:'',
            root:'data',
            totalProperty: 'results',
   fields:[
    { name:'so_pk_id',type:'int' },
    { name:'option_name',type:'string' }
    ]
});

The url property above contains the location to the PHP page that is querying the database. Autoload will ensure that the data is loaded in the store on page load and not at a later time. The fields must match the names given in the JSON file. We will also need a store that contains the data fro the main grid that this combo box will reside in, this code is :

var stoplight_grid_store = new Ext.data.JsonStore({
  storeId:'stoplight_grid_store',
  autoLoad:true,
  url:'mainGridStore.php',
  idProperty:'pk_light_id',
  root:'data',
  totalProperty: 'results',
        fields: [
            {name:'pk_light_id',type:'int' },
            {name:'color',type:'int' },
            {name:'name',type:'string' },
            {name:'location',type:'string' }
        ]
});

Now we need the code that creates the drop down box itself:

var options_dd = new Ext.form.ComboBox({
  triggerAction: "all",
  store: option_dd_store,
  displayField:'option_name',
  valueField:'so_pk_id',
  hiddenName:'so_pk_id'
});

Notice that we defined the store by passing the store variable, and we also defined a hiddenName, and value field as well as the displayField. The hidden field will become extremely important when we want to start passing the variable back to a page that will save the data to the database when it changes on the client side. Now it is time to place the code for the grid on the page.

var exec_type_rpt_sg_grid = new Ext.grid.EditorGridPanel({
          title: 'Stop Light Change Plan',
          store: 'stoplight_grid_store',
          id:'stoplight_grid',
          renderTo:'light_div',
          layout:'fit',
          height: 300,
          columns:[{
                          xtype: 'gridcolumn',
                          header: 'Light Color',
                          sortable: true,
                          resizable: true,
                          
                          width: 150,
                          dataIndex: 'color',
                          editor: options_dd,
                          renderer:function(value)
                                  { 
                                  var index = option_dd_store.find("so_pk_id",value);
                                  var displayName = option_dd_store.getAt(index).get("option_name"); 
                                  return displayName; 
                                  }
                       },{
                          xtype: 'gridcolumn',
                          header: 'Name',
                          sortable: true,
                          resizable: true,
                          width: 300,
                          dataIndex: 'name'
                       },{
                          xtype: 'gridcolumn',
                          header: 'Location',
                          sortable: true,
                          resizable: true,
                          width: 500,
                          dataIndex: 'location'
                       }
          ]
       });

So here is where the real world part of the example comes into play, when you have a table that contains lookup data in another table the main table (above) usually only has a reference to the primary key of the lookup table, so in order to display the ‘displayValue’ from your combo box in the grid opposed to the numerical value that would be the key you will need to use the renderer above which takes the vale from the grid and references it to the options_dd store and then returns the corresponding key.

Later this week we’ll go over updating the database behind the grid, but for now you have the ability to place a dependent dropdown box in the ExtJS grid and have the display value show opposed to the key.

A better editable grid, how search patterns revealed a desire for a decent drop down box inside a Ajax grid.

I have been getting a lot of traffic on the YUI drop down boxes inside of the YUI grid component, which leads me to believe that there are several individuals out there that need a decent editable grid with a decent drop down component. Well, at the risk of offending the Yahoo UI camp, I have to let it be known that many of the desperate search attempts and extensions of the YUI package can be satisfied by using another Javascript grid component altogether, in fact the post below will show you just how simple it is to set up a drop down box in an editable grid, which unlike the hack that was implemented for the YUI grid doesn’t rely on the eval function and can take data from a local array, JSON string, or better yet a data store populated from the database via lookup table.

First, to compare the two apples for apples let’s take a look at the Grid From Markup, to make the following example run in your environment first download the Ext JS package by following this link, http://www.sencha.com/products/js/download.php?dl=extjs321. Unzip the package to the folder where you have placed your website, an example is provided below:

Unzip the files and place the ext folder in the root of your project

The code for the grid from markup starts off much like the YUI grid, but that is where the similarities end, first cut    and paste the lines below to get the example running on your page.

<!HTML>
<html>
    <head>
        <title>Grid From Markup</title>

        <!-- These four links are all you need for all of the Ext components -->
        <link rel="stylesheet" type="text/css" href="/ext-3.2.1/resources/css/ext-all.css" />
        <script type="text/javascript" src="ext-3.2.1/adapter/ext/ext-base.js"></script>
        <script type="text/javascript" src="ext-3.2.1/ext-all.js"></script>
        <script type="text/javascript" src="ext-3.2.1/examples/ux/TableGrid.js"></script>

    </head>
    <body>
        <h1>Grid From Markup</h1>

       <table cellspacing="0" id="the-table">
        <thead>
            <tr style="background:#eeeeee;">
                <th>Name</th>
                <th style="width: 40px;">Age</th>
                <th>Sex</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Barney Rubble</td>
                <td>32</td>
                <td>Male</td>
            </tr>
            <tr>
                <td>Fred Flintstone</td>
                <td>33</td>
                <td>Male</td>
            </tr>
            <tr>
                <td>Betty Rubble</td>
                <td>32</td>
                <td>Female</td>
            </tr>
            <tr>
                <td>Pebbles</td>
                <td>1</td>
                <td>Female</td>
            </tr>
            <tr>
                <td>Bamm Bamm</td>
                <td>2</td>
                <td>Male</td>
            </tr>
        </tbody>
    </table>

    </body>
     <script>

              Ext.onReady(function(){
                      // create the grid
                      var grid = new Ext.ux.grid.TableGrid("the-table", {
                          stripeRows: true // stripe alternate rows
                      });
                      grid.render();
              });

        </script>
</html>

Not too much to it, there are four Ext scripts that will change this basic html table into a sortable data table ala YUI, and guess what, these four scripts will also do all of the other functions, like layout, menus, drag and drop, ……. No more hunting for the million includes, and no need for a separate app to just find out what order the include files should go in!

Here’s a look at the finished table, complete with sorting and hideable columns.

The simplest Ext grid still has sorting and hide-able columns.

The simplest Ext grid still has sorting and hide-able columns.



Changing your html table (made with markup) into a dynamic sortable html table with YUI (Yahoo User Interface)

Ajax Table

Sortable Table

To illustrate the power of Ajax in class one of the simplest and most striking examples is the progressive enhancement html datagrid. The yahoo user interface or YUI is a set of javascript widgets that you can incorporate into your page to instantly add functrionality such as drag and drop, dropdown menus, sortable and editable tables, layout, styled message boxes and much more. The focus of this article is a simple html table example. Let’s start with the following code which should produce a table that is your standard 1995 style html table.

The Code:

<html>
<head>
<title>Progressive YUI grid – step by step</title>
</head>
<body>

<table>
              <thead>
                            <tr>
                            <th>Some Value</th>
                            </tr>
              </thead>
              <tbody>
                            <tr>
                            <td>23</td>
                            </tr>
                             <tr>
                            <td>34</td>
                            </tr>
                             <tr>
                            <td>76</td>
                            </tr>
                             <tr>
                            <td>98</td>
                            </tr>
                            </tr>
              </tbody>
</table>
</body>
</html>

The Outcome:

Some Value
23
34
76
98

That’s all great, but you may want to offer sorting, movable columns, and a generally more appealing user interface for your tables. The first step to our table’s transformation is to add the links to the YUI scripts that will transform your table. Place the following into your tags.

<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.1/build/fonts/fonts-min.css">
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.1/build/datatable/assets/skins/sam/datatable.css">
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/element/element-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/datasource/datasource-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/datatable/datatable-min.js"></script>

The files above will transform your page by applying the CSS classes to the table and applying the Javascript that will give the table the ability to react to your mouse clicks. Now you might be wondering how get the links that you need and more importantly what order should they be put in. To answer that question you can go to http://developer.yahoo.com/yui/articles/hosting/ and click on the buttons corresponding to the widget that you want to use in your page, finally copying the code into the clipboard and pasting into your page.

Next you have to add the yui-skin-sam class to the tag in your page.

<body class="yui-skin-sam">

Now enclose the table in a div tag like the code below and give your table an id.

<div id="markup">
<table id="sometable">
<thead>
<tr>
<th>Some Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>23</td>
</tr>
<tr>
<td>34</td>
</tr>
<tr>
<td>76</td>
</tr>
<tr>
<td>98</td>
</tr>
</tbody>
</table>
</div>

Now under the closing div tag place the following script which will be explained after the code snippet.

<script type="text/javascript">
YAHOO.util.Event.addListener(window, "load", function() {
    YAHOO.example.EnhanceFromMarkup = function() {
        var myColumnDefs = [
            {key:"somevalue",label:"Something",sortable:true}
        ];

        var myDataSource = new YAHOO.util.DataSource(YAHOO.util.Dom.get("sometable"));
        myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
        myDataSource.responseSchema = {
            fields: [{key:"somevalue"}]
        };

        var myDataTable = new YAHOO.widget.DataTable("markup", myColumnDefs, myDataSource,
                {caption:"This is some caption",
                sortedBy:{key:"due",dir:"asc"}}
        );

        return {
            oDS: myDataSource,
            oDT: myDataTable
        };
    }();
});
</script>

Notice that ==> var myDataSource = new YAHOO.util.DataSource(YAHOO.util.Dom.get(“sometable”)); points to the id of the table. That is your datasource.

Now look at following and notice that markup is the name of the div that surrounds your table, this is where your new datatable will be drawn.

var myDataTable = new YAHOO.widget.DataTable("markup", myColumnDefs, myDataSource,
                {caption:"This is some caption",
                sortedBy:{key:"due",dir:"asc"}}
        );

Finally, here is the code for the simple example.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
		<title>My First YUI Table</title>
		<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.1/build/fonts/fonts-min.css">
		<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.1/build/datatable/assets/skins/sam/datatable.css">
		<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/yahoo-dom-event/yahoo-dom-event.js"></script>
		<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/element/element-min.js"></script>
		<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/datasource/datasource-min.js"></script>
		<script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/datatable/datatable-min.js"></script>
	</head>
	<body class="yui-skin-sam" >

		<div id="markup">
			<table id="sometable">
			<thead>
				<tr>
				<th>Some Value</th>
				</tr>
			</thead>
			<tbody>
				<tr>
				<td>23</td>
				</tr>
				<tr>
				<td>34</td>
				</tr>
				<tr>
				<td>76</td>
				</tr>
				<tr>
				<td>98</td>
				</tr>
			</tbody>
			</table>
		</div>
		<script type="text/javascript">
YAHOO.util.Event.addListener(window, "load", function() {
    YAHOO.example.EnhanceFromMarkup = function() {
        var myColumnDefs = [
            {key:"somevalue",label:"Something",sortable:true}
        ];

        var myDataSource = new YAHOO.util.DataSource(YAHOO.util.Dom.get("sometable"));
        myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
        myDataSource.responseSchema = {
            fields: [{key:"somevalue"}]
        };

        var myDataTable = new YAHOO.widget.DataTable("markup", myColumnDefs, myDataSource,
                {caption:"This is some caption",
                sortedBy:{key:"due",dir:"asc"}}
        );

        return {
            oDS: myDataSource,
            oDT: myDataTable
        };
    }();
});
</script>
	</body>
</html>

Dynamically Populating YUI Datatable Dropdown Editor Values

Updated on July 26, 2010 – There may be a better way to get a drop-down box inside an Ajax table, just take a look at this package.

One of the basic tasks that a developer often must perform is the generation of drop down box values, or radio box options from a dynamic source. The YUI
editable grid offers the drop down box as an option in the data table as an
editor choice. The problem that I have come across on several occasions is
that the drop down options that the editor will accept are in array format as
shown below:

By extending the YUI DropdownCellEditor (
http://developer.yahoo.com/yui/examples/datatable/dt_cellediting.html ) you
can add attributes to the select box and still keep the inherited classes in
the editor. Above the data table configuration call add the following code:

var myDynamicEditor = new YAHOO.widget.DropdownCellEditor();

Using the YUI Connection Manager
(http://developer.yahoo.com/yui/connection/) you can pull data in from
another page on load. This method requires one call to populate the
dropdownOptions of the editor’s select box.

// This line defines the page that will contain the data for the dropdown
options

var oUrl = 'dropdownDataReturn.asp?bustcache=' + new Date().getTime();

You may have noticed the inclusion of ‘?bustcache=’ + new Date().getTime();
‘appended to the URL of the data page, this ensures that every time you hit
the page you receive a non-cached version of the page.

The asp page queries a database table and outputs the data in the following
format. It is very important that this format be used otherwise the data can
not be imported into the editor:

["Option1"," Option2"," Option3"," Option4"," Option5"," Option6","
Option7"," Option8"," Option9"," Option10"]

To make the call back use the following code:

var callBack = {
success:function(o) {
try {
var optionsDD = o.responseText;
myDynamicEditor.dropdownOptions =
eval(optionsDD);
myDynamicEditor.render();
}
catch (e) {
alert(“Drop down Data Call failed!”);
return;
}
},
failure:function(o) {
alert(“Drop down Data Call
failed!”);
return;
},
scope:this
};

var request = YAHOO.util.Connect.asyncRequest(‘GET’, oUrl,  callBack);

Now you just have to use the extended drop down editor in the place of the
standard editor by using the code below in your data table configs:

var myColumnDefs = [
{ key:"platform", label:"Platform", sortable:true,editor:myDynamicEditor }
];