Custom Grid Editor

Word Count: 5712

Earlier today I wrote a short tutorial on grid editing. The tutorial walked you through on how you could easily edit your data right in a grid. While this is great it really is limited to certain use cases and on top of that we are limited with what the user can chose. In our example before we had a bunch of data including the state the artist lives in. If this were a full edit screen we would allow them to select a state from a drop down but in our grid it simply provides them a text box. What if there were a way to customize the editors for each field? Well there is and it really is not that hard. This tutorial will show you a state drop down box and hopefully Ill show you some more in the near future.

Like most of my grid tutorials we are going to use the cfartgallery data source that ships with ColdFusion 8. The first thing we are going to do is create our grid, make it editable and call a function named init after the page loads. If you have been following my grid tutorials this should look famailiar.

<cfquery name="getArtists" datasource="cfartgallery">
SELECT artistId, firstname, lastname, address, city, state, postalcode, email
FROM Artists
</cfquery>

<cfset args = structNew()>
<cfset args.name = "ArtistGrid">
   <cfset args.width = 600>
<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">
</cfgrid>
</cfform>

<cfset ajaxOnLoad("init")>
Now comes the real magic. First we need to get our grid object using the built in ColdFusion method getGridObject(). Next we need the column model and finally using the column model we can find out the index of our state column. The reason we need the index number will become clear in a second.
//grid object
grid = ColdFusion.Grid.getGridObject("ArtistGrid");
//column model cm = grid.getColumnModel();
//we need to know the column id stIndex = cm.findColumnIndex("STATE");
I am now going to create a combo box which will contain a list of all the states. Right now this will not show up or really do anything.
cb = new Ext.form.ComboBox({
id:"state",
mode:"local",
triggerAction:"all",
displayField:"text",
valueField:"value",
store:new Ext.data.SimpleStore({
fields: ["value", "text"],
data: [
['AL', 'Alabama'],
['AK', 'Alaska'],
['AZ', 'Arizona'],
['AR', 'Arkansas'],
['CA', 'California'],
['CO', 'Colorado'],
['CT', 'Connecticut'],
['DE', 'Delaware'],
['DC', 'District of Columbia'],
['FL', 'Florida'],
['GA', 'Georgia'],
['HI', 'Hawaii'],
['ID', 'Idaho'],
['IL', 'Illinois'],
['IN', 'Indiana'],
['IA', 'Iowa'],
['KS', 'Kansas'],
['KY', 'Kentucky'],
['LA', 'Louisiana'],
['ME', 'Maine'],
['MD', 'Maryland'],
['MA', 'Massachusetts'],
['MI', 'Michigan'],
['MN', 'Minnesota'],
['MS', 'Mississippi'],
['MO', 'Missouri'],
['MT', 'Montana'],
['NE', 'Nebraska'],
['NV', 'Nevada'],
['NH', 'New Hampshire'],
['NJ', 'New Jersey'],
['NM', 'New Mexico'],
['NY', 'New York'],
['NC', 'North Carolina'],
['ND', 'North Dakota'],
['OH', 'Ohio'],
['OK', 'Oklahoma'],
['OR', 'Oregon'],
['PA', 'Pennsylvania'],
['RI', 'Rhode Island'],
['SC', 'South Carolina'],
['SD', 'South Dakota'],
['TN', 'Tennessee'],
['TX', 'Texas'],
['UT', 'Utah'],
['VT', 'Vermont'],
['VA', 'Virginia'],
['WA', 'Washington'],
['WV', 'West Virginia'],
['WI', 'Wisconsin'],
['WY', 'Wyoming']
]
})
});
Finally each column has a defined editor. At the time the grid is built it is usually a text field or number field. To change the editor we need to set a new editor using the column models set editor method. This method takes 2 arguments, the index of the column (we got this earlier) and the new editor. The grid editor takes a form field definition. We are simply adding our combo box but this could easily be a date picker, color picker or custom editor.
cm.setEditor(stIndex,new Ext.grid.GridEditor(cb));

For those of you just joining me I am not running 8 so I can't show you a live demo but here are some images. When you double click the cell the combo box appears with the correct value selected. Then you can choose a state and when the combo box changes a new value is selected a red marker will appear noting that the value has changed.



Here is a the final code used for the example. As always please feel free to leave your questions or comments.
<cfsetting showdebugoutput="false">
<html>
<head>
<title>Edit Artist Grid</title>
<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("STATE");

cb = new Ext.form.ComboBox({
id:"state",
mode:"local",
triggerAction:"all",
displayField:"text",
valueField:"value",
store:new Ext.data.SimpleStore({
fields: ["value", "text"],
data: [
['AL', 'Alabama'],
['AK', 'Alaska'],
['AZ', 'Arizona'],
['AR', 'Arkansas'],
['CA', 'California'],
['CO', 'Colorado'],
['CT', 'Connecticut'],
['DE', 'Delaware'],
['DC', 'District of Columbia'],
['FL', 'Florida'],
['GA', 'Georgia'],
['HI', 'Hawaii'],
['ID', 'Idaho'],
['IL', 'Illinois'],
['IN', 'Indiana'],
['IA', 'Iowa'],
['KS', 'Kansas'],
['KY', 'Kentucky'],
['LA', 'Louisiana'],
['ME', 'Maine'],
['MD', 'Maryland'],
['MA', 'Massachusetts'],
['MI', 'Michigan'],
['MN', 'Minnesota'],
['MS', 'Mississippi'],
['MO', 'Missouri'],
['MT', 'Montana'],
['NE', 'Nebraska'],
['NV', 'Nevada'],
['NH', 'New Hampshire'],
['NJ', 'New Jersey'],
['NM', 'New Mexico'],
['NY', 'New York'],
['NC', 'North Carolina'],
['ND', 'North Dakota'],
['OH', 'Ohio'],
['OK', 'Oklahoma'],
['OR', 'Oregon'],
['PA', 'Pennsylvania'],
['RI', 'Rhode Island'],
['SC', 'South Carolina'],
['SD', 'South Dakota'],
['TN', 'Tennessee'],
['TX', 'Texas'],
['UT', 'Utah'],
['VT', 'Vermont'],
['VA', 'Virginia'],
['WA', 'Washington'],
['WV', 'West Virginia'],
['WI', 'Wisconsin'],
['WY', 'Wyoming']
]
})
});

cm.setEditor(stIndex,new Ext.grid.GridEditor(cb));

}
</script>
</head>

<body>

<link href="/CFIDE/scripts/ajax/ext/resources/css/ytheme-aero.css" rel="stylesheet" type="text/css">

<cfquery name="getArtists" datasource="cfartgallery">
SELECT artistId, firstname, lastname, address, city, state, postalcode, email
FROM Artists
</cfquery>

<cfset args = structNew()>
<cfset args.name = "ArtistGrid">
   <cfset args.width = 600>
<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">
</cfgrid>
</cfform>

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

Comments

#1 Posted By: joshua cyr Posted On: 3/12/08 5:35 PM
Just wanted to say that this entire series is very very cool. I may not have need right now, but I know where to go looking when I do. Thanks for blogging it all.
#2 Posted By: Mike Posted On: 3/12/08 6:00 PM
I second what Joshua said...very useful series. Here's one for the editable grid topic...insert capabilities. Can it be done with cfgrid in html mode (with tweaking)? Thanks for all your work!
#3 Posted By: Dan Vega Posted On: 3/12/08 8:19 PM |
Author Comment
Thanks for the comments guys! As long as someone thinks it worth reading I will keep posting.

@Mike - Inline editing is for certain purposes. When you are displaying data for a grid you are really just displaying the important data. When you need to add a record you are much better off displaying a new form or a window with a more complete form. Adding an add button to the toolbar and opening a cfwindow sounds like a perfect fit there.
#4 Posted By: Anuj Gakhar Posted On: 3/13/08 5:02 AM
@Dan, thats right. After looking at your examples, I actually did an example of a complete Add/Edit/Delete Capability via CFGRID. It uses CFWindow for add and Cfwindow as well for delete confirmation. Works really well. I might blog about it as well.
#5 Posted By: Frank Wheatley Posted On: 3/13/08 7:41 AM
I might use this and make the arg structure dynamic if the user is logged in. Thanks for the examples.
#6 Posted By: Brian Posted On: 3/13/08 11:15 AM
Thanks for the quick overview on adding in this functionality. Getting past the comboBox for the editor option in the gridPanel wasn't a problem for me, but have you had any luck implementing the checkBox?

Also, one of the CF User Group members gave a great overview of creating a CRUD interface with the grid a while back. You can find the entry on his blog at:

http://webtrenches.com/post.cfm/ajax-features-in-c...

Sample CRUD interface is located at:
http://webtrenches.com/ajaxpreso/samples/sampleapp...

Although this implementation doesn't utilize <cfwindow>, its a great starting point for anything beginning to work with CF8 Ajax and Grid functionality
#7 Posted By: Dan Vega Posted On: 3/13/08 11:26 AM |
Author Comment
What are you trying to do with a checkbox?
#8 Posted By: Brian Posted On: 3/13/08 12:05 PM
@Dan: Lets say I have bit field that I want to be editable, the checkbox would toggle the bit field on/off.
#9 Posted By: Anuj Gakhar Posted On: 3/18/08 8:33 AM
Dan, just posted this, however a lot of the credit goes to you for posting these examples.
http://www.anujgakhar.com/2008/03/18/crud-with-cfg...
#10 Posted By: Justin Posted On: 3/27/08 5:33 PM
Hi Dan, your tutorials are great! Just wondering if you know how to add a confirmation alert to cfgrid's delete button action. Currently, I just override the deleteRow function defined in cfgrid.js. I know this solution isn't a good idea, but is there another way to do it? I know I can just create a button that can make an ajax call to delete a record in the grid.
#11 Posted By: Brian W Posted On: 4/23/08 5:09 PM
Dan - When I use the full code example you provided (copied and pasted straight from you example) I get a functional, editable grid, but no select menu in the state field. I can edit the field, but there is no drop down.

I've looked through the code several times and can't seem to pinpoint the issue.

Any thoughts or ideas?
#12 Posted By: Dan Vega Posted On: 4/23/08 7:37 PM |
Author Comment
This is example was created before I found out about a much more efficient solution. Check out this post > http://www.danvega.org/blog/index.cfm/2008/3/28/Co...
#13 Posted By: Carla Scepaniak Posted On: 5/29/08 6:00 PM
Has anyone figured out the checkbox issue? No matter what I try, all it will display is true/false, when you double-click the cell the checkbox appears; click out, and it goes to true or false.

I have an html grid bound to a cfc, the checkbox column was created by array/querynew/queryaddcolumn, and I need a checkbox so the user can tell me they want the changes applied in one row to apply to all the people associated with the id of that row. Since you apparently can't make multiple selections on a drop-down box (or can you, because that would solve my entire problem), I figured I needed a trigger to tell me to use the changes in that one row for other records so the user wouldn't have to type the same data in multiple rows. Not at all a nice solution, but so far has been the only one in my particular situation. Help help help......
#14 Posted By: Lonnie Posted On: 8/21/08 3:37 PM
Scratch that request, I figured out that your complete example had commented out the variables for grid, cm, and stIndex. Problem solved.
#15 Posted By: jono Posted On: 12/12/08 11:30 AM
Hi guys, I'm new in cf, I already have a cfgrid load (bind to a data base table ) in html from a table releated to another one, with foreign key, but I dont wanna show the id of the key, I want to show the value or description of the foreign key, how do i do this? how can I take a cfgridcolumn and show the value or make a bind of the value of other table?
#16 Posted By: David Jacobson Posted On: 4/28/10 2:06 PM
Dan,

Any ideas how to do this when teh datasource is a query and not hardcoded like you have it? Here is my issue:

My grid provides the correct drop down list but when displaying the value of the column it shows the actual value and not the display value that I want. It should be showing the name and not the ID for those names stored in the database.


<cfgridcolumn name="ship_class_id" header="Class" width="75" values="#valuelist(getClass.ship_class_id)#" valuesdisplay="#valuelist(getClass.ship_class)#" />

Any Ideas?
#17 Posted By: Dan Vega Posted On: 5/1/10 10:04 AM |
Author Comment
David - How are you getting the value of the drop down? When you look at the source can you see the class_id ?
#18 Posted By: David Jacobson Posted On: 5/3/10 9:00 AM
I do get the value of the class_id and the dropdown displays the name as it should, however when the dropdown is not activated the column shows the class_id and not the class name.

I want the column to work like the dropdown. I think it's because of the dynamic update query that it is doing this but I'm not sure.

-David
#19 Posted By: Jessica Posted On: 6/7/10 6:50 PM
@David or Dan,

I have the same problem when a CFGRID row is selected. My drop down displays the actual ID value of the selection rather than the display value. Any tips on how to correct this issue? Thanks!

-Jessica


Post Your Comment

Leave this field empty







Show Captcha

If you subscribe, any new posts to this thread will be sent to your email address.

Copyright © 2007 Dan Vega | BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.