CFGrid Date Picker Editor
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>
<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>






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)?
http://cfext.riaforge.org
I'm having trouble with correctly formatting the date for the update query.
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."
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.
<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>
You saved the day and a project. I will try this and let you know if it works for me.
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!!!
put this in your page.
<code>
<style>
.x-date-picker{
width:150px;
}
</style>
</code>
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.
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.
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