Adding an ADD button for cfgrid
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 a
from 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.
Comments
Another cool option that Stroz thought of is to add a double click listener to each row and open a cfwindow on double click...
I don't believe you want "javascript:" on the onclick event.
Pat
Patrick: Why doesn't he want that?
@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.
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+.
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".
/*** ART_LIST.CFM file contents ***/
<script>
function testit(x) { alert(x);}
</script>
<cfform name="form" action="act_art.cfm" method="post" format="html">
<table>
<tr>
<th>Module Categories</th>
<td>
<cfselect bindonload="true" name="varCategory" bind="cfc:cfc.art.GetCategories()"/>
</td>
</tr>
</table>
<cfgrid name="ArtList" bindonload="false" format="html" pagesize="20" striperows="yes" width="700"
bind="cfc:cfc.art.GetArt({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},{varCategory})">
<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" />
</cfgrid>
</cfform>
/*** 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,
art_categories.category_name
FROM art_categories
ORDER BY category_name
</cfquery>
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.categoryid[i]>
<cfset result[i][2]=data.category_name[i]>
</cfloop>
<cfreturn result>
</cffunction>
<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,
art_title,
artist_name
FROM art
WHERE categoryid=#varCategory#
<cfif ARGUMENTS.gridsortcolumn NEQ "" and ARGUMENTS.gridsortdir NEQ "">
ORDER BY #ARGUMENTS.gridsortcolumn# #ARGUMENTS.gridsortdir#
<cfelse>
ORDER BY artist_name,art_title
</cfif>
</cfquery>
<cfset queryAddColumn(data, "add", arrayNew(1))>
<cfloop query="data">
<cfset querySetCell(data, "add", "<input value='Add' type='button' onclick='javascript:testit(#module_id#)'>", currentrow)>
</cfloop>
<cfreturn QueryConvertForGrid(data, ARGUMENTS.page, ARGUMENTS.pageSize)>
</cffunction>
Ron
<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.
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
onclick="javascript:testit(#art_id#)"
http://blog.cutterscrossing.com/index.cfm/2007/11/...


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.
Thanks!