Adding an ADD button for cfgrid

This post is more than 2 years old.

Here is a question forwarded to me from Ben Forta. He thought I could take a stab at it so here is my answer.

I am putting a query result set into afrom a cfc bind statement (which works with no problem). What I want to be able to do is have one grid column with an "ADD" button in it. When the button/cell is clicked it invokes another function that writes some data to a database. Everything I have read only addresses the edit/delete mode of the grid data itself. I want to "click" the item and have it add to another list/container/database.

This is something I kind of touched on before. When you pass a query to a cfgrid, you can include HTML in the query data. This HTML will render in the grid. So consider the following code. <cfquery name="entries" datasource="cfartgallery" maxrows="12"> select * from art </cfquery>

<cfset queryAddColumn(entries, "add", arrayNew(1))>

<cfloop query="entries"> <cfset querySetCell(entries, "add", "<input value='Add' type='button' onclick='javascript:testit(#artid#)'>", currentrow)> </cfloop>

I took a simple query and added a new column, "add". I looped over the query and for each row, added an HTML button that calls a JavaScript function and passes the primary key of the row.

Just to ensure it works, here is the rest of the code:

<script> function testit(x) { alert(x);} </script>

<cfform name="test"> <cfgrid autowidth="true" name="entries" format="html" query="entries" width="600"> <cfgridcolumn name="artid" display="false">

<cfgridcolumn name="artname" header="Name"> <cfgridcolumn name="price" header="Price"> <cfgridcolumn name="add" header="Add"> </cfgrid> </cfform>

If you run this in your browser, you can click on any button and see the JavaScript called. So that's the difficult part really. If you want to pass this 'add action' to the server, you can use cfajaxproxy. I assume this part is easy, if folks want to see that part of the code, I can work that up as well.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Nolan Erck posted on 3/4/2008 at 12:22 AM

Hi Ray,

Thanks for the post -- I've been meaning to look into this for a while and havent had the time. If you have a sec, I'd like to see the "add action" code via an AjaxProxy that you mentioned. I've yet to see a good "real world" example of cfajaxproxy out there anywhere in blogland.


Comment 2 by todd sharp posted on 3/4/2008 at 12:44 AM

If you're doing this on every row, wouldn't it be more of an 'Edit' button then an 'Add'? Yeah, I know...semantics ;)

Another cool option that Stroz thought of is to add a double click listener to each row and open a cfwindow on double click...

Comment 3 by Raymond Camden posted on 3/4/2008 at 12:48 AM

I don't think his intent was to be an Edit, but more a 'Here is a list of data. Select the ones you want on your page', so Add would make sense. You would then want to change the button on the fly to a remove.

Comment 4 by Patrick Whittingham posted on 3/4/2008 at 1:01 AM

Ray -

I don't believe you want "javascript:" on the onclick event.


Comment 5 by todd sharp posted on 3/4/2008 at 1:02 AM

Ray: I get ya now...

Patrick: Why doesn't he want that?

Comment 6 by Sam Farmer posted on 3/4/2008 at 1:03 AM

Nice. Anyone know how to turn paging off for cfgrid? Yeah, yeah, I know thats one of the main points of cfgrid but my client wants to see it all on one page.

Comment 7 by Raymond Camden posted on 3/4/2008 at 1:05 AM

@Pat - you are right - although it seemed to work.

@Sam - use the pagesize attribute. You would need to do a CF query before hand though to get the count, but that is a very small query.

Comment 8 by Patrick Whittingham posted on 3/4/2008 at 1:16 AM

Ray -

The only time you need it is with the "Href" part of the anchor tag <a href="javascript:x(); " >aaa</a>

Actually, the onclick for that tag is better..that "href="javascript:" is part of IE 5 and Netscape 4+.

Comment 9 by Jim Ruzicka posted on 3/4/2008 at 1:26 AM

Somewhat off topic, but do you get hyphen hyperlinks in your cfgrid rows that are empty? If the grid accepts 10 rows, but the resultset only has 8 rows...the last two rows will be filled with hyperlinked hyphens with a cfgridkey=null. Do you know how to get rid of them? Any assistance is greatly appreciated. Thanks.

Comment 10 by Ron McKay posted on 3/4/2008 at 1:58 AM

Hey, I was the one that originally asked about this capability and Ray I appreciate you addressing it so quickly. I am going to take your suggestion and see if I can apply it into my logic. I will update you on the attempt.

For those that was asking why...The intended use of something like this is to allow someone to pick an item from a cfgrid result list and by selecting the "ADD" button from a cfgridcolumn it would insert that item into their "basket" which in this case is an associated database table insert. The basket display box would have a bind statement that would asynchronously pull what was current in their basket. I felt that the cfgrid was a better/easier display method opposed to just a standard <table> layout. Right or wrong...I was attempting to let the cfgrid be my "table layout".

Comment 11 by Ron McKay posted on 3/4/2008 at 2:05 AM

Oh...and the <cfajaxproxy> concept would also be helpful.

Comment 12 by Ron McKay posted on 3/4/2008 at 2:53 AM

This is working great!!! I wanted to post an example of my code up to this point, and following along with the "art theme" that Ray used.

/*** ART_LIST.CFM file contents ***/
function testit(x) { alert(x);}

<cfform name="form" action="act_art.cfm" method="post" format="html">
<th>Module Categories</th>
<cfselect bindonload="true" name="varCategory" bind=""/>

<cfgrid name="ArtList" bindonload="false" format="html" pagesize="20" striperows="yes" width="700"
<cfgridcolumn name="art_id" display="false"/>
<cfgridcolumn name="art_title" header="Title" width="300" select="false" />
<cfgridcolumn name="artist_name" header="Lang" width="50" select="false" />
<cfgridcolumn name="add" header="ADD IT!" width="50" />

/*** ART.CFC file contents ***/
<cffunction name="GetCategories" access="remote">
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<cfquery name="data" datasource="art_db">
SELECT art_categories.categoryid,
FROM art_categories
ORDER BY category_name
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.categoryid[i]>
<cfset result[i][2]=data.category_name[i]>
<cfreturn result>
<cffunction name="GetArt" access="remote" returntype="struct">
<cfargument name="page" type="numeric" required="yes">
<cfargument name="pageSize" type="numeric" required="yes">
<cfargument name="gridsortcolumn" type="string" required="no" default="">
<cfargument name="gridsortdir" type="string" required="no" default="">
<cfargument name="varCategory" type="any" required="yes" default="0">

<cfquery name="data" datasource="art_db">
SELECT art_id,
FROM art
WHERE categoryid=#varCategory#
<cfif ARGUMENTS.gridsortcolumn NEQ "" and ARGUMENTS.gridsortdir NEQ "">
ORDER BY #ARGUMENTS.gridsortcolumn# #ARGUMENTS.gridsortdir#
ORDER BY artist_name,art_title
<cfset queryAddColumn(data, "add", arrayNew(1))>
<cfloop query="data">
<cfset querySetCell(data, "add", "<input value='Add' type='button' onclick='javascript:testit(#module_id#)'>", currentrow)>
<cfreturn QueryConvertForGrid(data,, ARGUMENTS.pageSize)>

Comment 13 by Raymond Camden posted on 3/4/2008 at 2:56 AM

Cool. Do folks still want to see me expand on my code to show hooking it up with cfajaxproxy?

Comment 14 by Ron McKay posted on 3/4/2008 at 3:02 AM

Ray, I think it would help provide a total scenario for others looking how to do this. I say this after searching the web for a couple of days on implementing <cfgrid> mixed with form types of uses. There was not a lot being directly said about it and I think others would find it helpful.


Comment 15 by Ron McKay posted on 3/4/2008 at 3:04 AM

one fix on my post....

<cfset querySetCell(data, "add", "<input value='Add' type='button' onclick='javascript:testit(#module_id#)'>",currentrow)>

should say #art_id# instead of #module_id#
<cfset querySetCell(data, "add", "<input value='Add' type='button' onclick='javascript:testit(#art_id#)'>",currentrow)>

Sorry about that...bad copy/paste from my orig code.

Comment 16 by Sam Farmer posted on 3/4/2008 at 3:12 AM


You could also just append to the original column the add button:

SELECT art_ID, art_name, '<input type="button" value="Add">' as addButton
FROM artists

thats scratch code not sure exactly what the syntax is for Derby db

Comment 17 by Raymond Camden posted on 3/4/2008 at 3:30 AM
Comment 18 by Ron McKay posted on 3/4/2008 at 3:36 AM

Sam, by adding the button as part of your SELECT I don't think you are able to pass the "ART_ID" variable within the javascrip statement...


Comment 19 by Raymond Camden posted on 3/4/2008 at 3:42 AM

He could mod it to use concatation and add the artid value.

Comment 20 by Steve &aposCutter&apos Blades posted on 3/4/2008 at 7:16 PM

@Ray - I put up a similar entry on this exact issue back in November, but took a slightly different approach:


Comment 21 by Chaz posted on 2/23/2009 at 9:47 PM

When displaying a button in cfgrid does the format have to be ‘html’?

When I us flash as the format I see the string value of the cell, but when I change it to html I get an error saying ‘Attribute validation error for tag CFGRID.The value of the attribute FORMAT, which is currently "html", must be one of the values: APPLET,FLASH,XML.’

What am I doing wrong!!!


Comment 22 by Raymond Camden posted on 2/23/2009 at 9:49 PM

Flash form grids are a completely different beast. I recommend you don't use them. If you want a Flash based grid, use Flex.

The error you get sounds like you aren't on CF8.