CFGrid Date Picker Editor

Posted By : todd sharp Posted At : April 7, 2008 4:29 PM Posted In: Ext, Ajax, ColdFusion

28

A few weeks ago Dan Vega blogged about creating a comboxbox (drop down) cell editor for the editable <cfgrid> before he realized that cfgrid supports in cell drop downs. I commented that I'd like to see something like a date picker cell editor and after using Dan's orginal code as inspiration and some hints from this post by Scott Bennett I finally got the thing working. Yes, I do realize that sometimes it'd just be easier to roll your own Ajax widget from scratch, but sometimes hacking it is more fun.

I'll leave it to Dan and Scott's original posts to explain the details, but here is what you'll end up with:

And here's the code:

<cfsetting showdebugoutput="false">

<cfajaximport tags="cfinput-datefield" />

<html>
<head>
<title>Edit Artist Grid</title>
<link href="/CFIDE/scripts/ajax/ext/resources/css/ytheme-aero.css" rel="stylesheet" type="text/css">

<style>
.x-menu-list{
margin: 0px; padding: 0px;
}
</style>

<script type="text/javascript" src="/CFIDE/scripts/ajax/ext/ext-all.js"></script>

<script type="text/javascript">
function init(){
//grid object

grid = ColdFusion.Grid.getGridObject("ArtistGrid");

//column model

cm = grid.getColumnModel();

//we need to know the column id

stIndex = cm.findColumnIndex("LASTMODIFIED");

var df = new Ext.grid.GridEditor(
    new Ext.form.DateField(
        {
            format: 'm/d/Y',
            minValue: '04/01/08',
        }
    )
);


cm.setEditor(stIndex, df);
cm.setRenderer(stIndex, Ext.util.Format.dateRenderer('m/d/Y'));

grid.reconfigure(grid.getDataSource(),cm);
}
</script>
</head>

<body>



<cfquery name="getArtists" datasource="cfartgallery">
SELECT artistId, firstname, lastname, address, city, state,
postalcode, email, '04/01/2008' as lastModified
FROM Artists
</cfquery>

<cfset args = structNew()>
<cfset args.name = "ArtistGrid">

<cfset args.format = "html">
<cfset args.query = "getArtists">
<cfset args.stripeRows = true>
<cfset args.selectColor = "##D9E8FB">
<cfset args.selectmode = "edit">
<cfset args.onchange = "cfc:artists.editArtist({cfgridaction},{cfgridrow},{cfgridchanged})">

<cfform>
<cfgrid attributeCollection="#args#">
<cfgridcolumn name="artistid" display="false">
<cfgridcolumn name="firstname" header="First Name">
<cfgridcolumn name="lastname" header="Last Name">
<cfgridcolumn name="address" header="Address">
<cfgridcolumn name="city" header="City">
<cfgridcolumn name="state" header="State">
<cfgridcolumn name="postalcode" header="Zip">
<cfgridcolumn name="lastModified" header="Last Modified">
</cfgrid>
</cfform>

<cfset ajaxOnLoad("init")>
</body>
</html>

Comments (28)

Trond Ulseth's Gravatar Nice example Todd.

I know that if I google and try for some hours I'd maybe find out by myself, but I figure you could probably answer from the top of your head: How can I use the same datefield picker in a "normal" cfform (not in a grid)?

todd sharp's Gravatar Well, I think your best bet would be to check out Dan Vega's cfext project - I believe he has a custom tag for that.

http://cfext.riaforge.org

Kevin Jamison's Gravatar This is awesome. I have been trying to do this since last fall. Do you have a working demo? I am having trouble getting it to work (datepicker).

todd sharp's Gravatar What goes wrong Kevin?

Kevin Jamison's Gravatar Hi Todd, when the page loads in IE I get an error:"init" is undefined and it is just a plain grid. In Safari it loads and the datepicker shows up, but the database doesn't update on refresh (changes will update in IE). Thanks for any help and thanks for the AWESOME site, it is a great help!

Yvonne Shevnin's Gravatar Would you be willing to post your cfc?

I'm having trouble with correctly formatting the date for the update query.

Jackie's Gravatar This is awesome

Sheila Handler's Gravatar This works great in Firefox but I get a similar JS error to Kevin when I load it in IE6 and IE7. It's having trouble with this line:

ColdFusion.Event.registerOnLoad(init,null,false,true);

which is what the ajaxonload gets expanded to. The error is "Expected identifier, string or number". If you click OK to that js alert, it then says "init is not defined."

todd sharp's Gravatar Just a hunch, but try renaming the init function to something else? Maybe 'init' is a reserved word in IE?

Sheila Handler's Gravatar No, I renamed it to "wasinit". Same problem. Have you run this successfully in IE6 or IE7?

Sheila Handler's Gravatar To isolate the error, I commented out these statements:

var df = new Ext.grid.GridEditor(
new Ext.form.DateField(
{
format: 'm/d/Y',
minValue: '04/01/08',
}
)
);


cm.setEditor(stIndex, df);

and the js error goes away (of course, so does the date picker). It seems IE doesn't like this syntax.

todd sharp's Gravatar OK I've figured it out. Seems there is issues with the generated JavaScript - CF is putting the code to create the grid after my script, so the grid doesn't exist when I try to create the renderer. The solution is to wrap the init script in a cfsavecontent and then use cfhtmlhead to write that to the head. Code below:

<cfsetting showdebugoutput="false">

<cfajaximport tags="cfinput-datefield" />

<html>
<head>
<title>Edit Artist Grid</title>
<link href="/CFIDE/scripts/ajax/ext/resources/css/ytheme-aero.css" rel="stylesheet" type="text/css">

<style>
.x-menu-list{
margin: 0px; padding: 0px;
}
</style>

<script type="text/javascript" src="/CFIDE/scripts/ajax/ext/ext-all.js"></script>

</head>

<cfsavecontent variable="js">
<script type="text/javascript">
init = function(){
//grid object

grid = ColdFusion.Grid.getGridObject("ArtistGrid");

//column model

cm = grid.getColumnModel();

//we need to know the column id

stIndex = cm.findColumnIndex("LASTMODIFIED");

var df = new Ext.grid.GridEditor(
   new Ext.form.DateField(
      {
         format: 'm/d/Y',
         minValue: '04/01/08'
      }
   )
);


cm.setEditor(stIndex, df);
cm.setRenderer(stIndex, Ext.util.Format.dateRenderer('m/d/Y'));

grid.reconfigure(grid.getDataSource(),cm);
}
</script>
</cfsavecontent>
<cfhtmlhead text="#js#" />
<cfset ajaxOnLoad("init") />
<body>


<a href="javascript:init();">init</a>
<cfquery name="getArtists" datasource="cfartgallery">
SELECT artistId, firstname, lastname, address, city, state,
postalcode, email, '04/01/2008' as lastModified
FROM Artists
</cfquery>

<cfset args = structNew()>
<cfset args.name = "ArtistGrid">

<cfset args.format = "html">
<cfset args.query = "getArtists">
<cfset args.stripeRows = true>
<cfset args.selectColor = "##D9E8FB">
<cfset args.selectmode = "edit">
<cfset args.onchange = "cfc:artists.editArtist({cfgridaction},{cfgridrow},{cfgridchanged})">

<cfform>
<cfgrid attributeCollection="#args#">
<cfgridcolumn name="artistid" display="false">
<cfgridcolumn name="firstname" header="First Name">
<cfgridcolumn name="lastname" header="Last Name">
<cfgridcolumn name="address" header="Address">
<cfgridcolumn name="city" header="City">
<cfgridcolumn name="state" header="State">
<cfgridcolumn name="postalcode" header="Zip">
<cfgridcolumn name="lastModified" header="Last Modified">
</cfgrid>
</cfform>

</body>
</html>

Sheila Handler's Gravatar Thank you! Thank you! Thank you!
You saved the day and a project. I will try this and let you know if it works for me.

Sheila Handler's Gravatar It works perfectly in IE. Thanks again, Todd.

Kevin Jamison's Gravatar You are awesome, it works! Thanks for all your time.

Carla Scepaniak's Gravatar Totally awesome, you have saved my life with this one!!! Thank you so much for your blog. I have my grid opening in a modal cfwindow, and it's so cool; I have two date selection columns, so I just adjusted the javascript a little bit.

Now I have a few questions, kinda related:

1) Within an html edit grid utilizing cfcs, is there any way to have a select list which allows multiple selections?

2) I am confused about how to call my cfcs in the bind/onchange attributes if they reside in the cf8/CustomTags folder on my c drive (and the websites are on another drive). I can't seem to find an actual example of the exact syntax to use, help?

3) I'm very new to the ext stuff and at this time am totally confused about how to install whatever's needed to use the stylesheets such as you use (ytheme-aero.css), because I really like how they render a grid. Is it too complicated, or is it something which can be explained to me? I've been looking around the extjs.com site, but I just don't seem to be getting it yet. Also, do I look at the 1.1 ext material for ColdFusion or 2.0?

Thank you so much!!!

sneha's Gravatar Has anyone tested this with Firefox 3.0, the calender doesn't render properly. Its way too wide, numbers missing & unable to make selections..anyone has a fix?

David Fry's Gravatar sneha,

put this in your page.

<code>
<style>
.x-date-picker{
   width:150px;
}
</style>
</code>

Giedrius's Gravatar Man, saved wrapping init in cfcontent saved me lots of time and headaches, too! Thanks!

Henry Ho's Gravatar I just got this date picker to work, thank you!

TIPS:

1.) always use 'yyyy/mm/dd' date format in the date column. Format it form the DB when you do the SELECT! So that you can use Ext's built-in dateRenderer without writing one yourself.

2.) if you made the CFGIRD editable, you need to know that the output of the datepicker is not the format you specify in {format: ''}. It is in what they call SortableDateTime format, see: http://www.yui-ext.com/deploy/ext-1.1.1/docs/outpu... . Basically just grab the date part at the front with left(10), then do a ParseDateTime() to turn it into a Date obj in Cf.

Henry Ho's Gravatar @Carla Scepaniak,

1) Within an html edit grid utilizing cfcs, is there any way to have a select list which allows multiple selections?

> why would you want to have a multiple selections? Usually, once cell represent one entry in your query (from DB). If you really need multiple selections, I would recommend you to bind your row into a CFDIV, and render a proper HTML form in that CFDIV to support multiple selections.

2) I am confused about how to call my cfcs in the bind/onchange attributes if they reside in the cf8/CustomTags folder on my c drive (and the websites are on another drive). I can't seem to find an actual example of the exact syntax to use, help?
> write a remote method that use your custom tag, then bind you cfgrid to your remote method using "CFC:"

3) I'm very new to the ext stuff and at this time am totally confused about how to install whatever's needed to use the stylesheets such as you use (ytheme-aero.css), because I really like how they render a grid. Is it too complicated, or is it something which can be explained to me? I've been looking around the extjs.com site, but I just don't seem to be getting it yet. Also, do I look at the 1.1 ext material for ColdFusion or 2.0?
> CF8.01 uses Ext 1.1.1. To use those css skins, just import them like how you'd import any CSS using LINK. You can use the CFSAVECONTENT together with CFHTMLHEADER trick if you like.

Aaron's Gravatar Hi,

I have your example working and for the most part its great. How can you stop people from entering their own date via the keyboard (ie. only select a date from the date picker)?

Also, when a user clicks on the date cell the date dissapears and it goes blank to accept a user defined date. But then if the user opens the date selector but pick nothing and then clicks on another cell, that last date cell appears empty. How do youstop that? And last of all, what does: minValue: '04/01/08' do?

Cheers

Brian's Gravatar important note that it took me a little while to figure out while adding it to my page... on this line.
stIndex = cm.findColumnIndex("LASTMODIFIED");

the name of the column has to be in uppercase, even if you used lowercase to define it.

Sam Farmer's Gravatar Todd,

Very cool. Not only does this work completely fine in CF9 but also date is now a valid option for cfgridcolum.

Roe's Gravatar Hey Dan I found a display bug with this code in FF3 here's a link to what I saw: http://www.extjs.com/forum/showthread.php?t=61974

If you add table.x-date-inner{width:130px;table-layout:fixed;} to your page anywhere after the ext css is included it will fix this display problem

Francesco's Gravatar how can I submit checkbox in cfgrid?

Shaun's Gravatar Hi I am working on using this all over the place in my application. The only problem I am having is that my date picker is not fully rendering. It seems like it's functioning well but the calendar days are not displaying.

Shaun's Gravatar I figured it out!!!! Whoo Hoo!!!!
I had previously put the
<cfajaximport tags="CFFORM,CFGRID,CFINPUT-DATEFIELD">
At the top of my page.

This workaround conflicts with the CF tags so I had to remove the
CFINPUT-DATEFIELD

Now it works perfectly!!!!!
Thank you everyone for all the work.
I'll be adding links to this stuff on my own blog in the next couple of days!

Oh and by the way I have this working on multiple columns by just adding columns to the script:

<script type="text/javascript">
function init(){
   //grid object
   grid = ColdFusion.Grid.getGridObject("projects_grid");
   //column model
   cm = grid.getColumnModel();
   //we need to know the column id
   stIndex = cm.findColumnIndex("P_SUBMITTED_DATE");
   stIndex2 = cm.findColumnIndex("P_PRJ_START_DATE");
   var df = new Ext.grid.GridEditor(
      new Ext.form.DateField(
         {
            format: 'm/d/Y',
            minValue: '04/01/08',
         }
      )
   );
   cm.setEditor(stIndex, df);cm.setEditor(stIndex2, df);
   cm.setRenderer(stIndex, Ext.util.Format.dateRenderer('m/d/Y'));cm.setRenderer(stIndex2, Ext.util.Format.dateRenderer('m/d/Y'));
   grid.reconfigure(grid.getDataSource(),cm);
}
</script>

You can probably use this in multiple columns throughout by doing a javascript loop function and look for date formats.
Very cool! Thank you.