ColdFusion 8 cfgrid adding Add and Delete Record Functionality
The ColdFusion 8 cfgrid offers us an excellent interface to allow our application users to perform administrative tasks on table data. Two fundamental functions on table data include the ability to Add a Record and the ability to Delete a Record. So, I modified the cfgrid that has been built till now (blogged previously) to include Add/Delete functionality.
You can look at a Demo Here
For the Add function, we "pop-up" a window asking for information. When the user is done entering that, we call a CFC to add the information to the database and refresh the grid. The Add User button calls the saveUser() JS function that does this.
1 function saveUser()
2 {
3 var objForm = document.addUserForm
4 var stcForm = {};
5 stcForm.FirstName = objForm.FirstName.value;
6 stcForm.LastName = objForm.LastName.value;
7 stcForm.DisplayName = objForm.DisplayName.value;
8 stcForm.UserName = objForm.UserName.value;
9 stcForm.UserAccountingCode = objForm.UserAccountingCode.value;
10 stcForm.Phone = objForm.Phone.value;
11 stcForm.Password = objForm.Password.value;
12 objUser.addUser(stcForm);
13 ColdFusion.Window.hide('addUser');
14 }
2 {
3 var objForm = document.addUserForm
4 var stcForm = {};
5 stcForm.FirstName = objForm.FirstName.value;
6 stcForm.LastName = objForm.LastName.value;
7 stcForm.DisplayName = objForm.DisplayName.value;
8 stcForm.UserName = objForm.UserName.value;
9 stcForm.UserAccountingCode = objForm.UserAccountingCode.value;
10 stcForm.Phone = objForm.Phone.value;
11 stcForm.Password = objForm.Password.value;
12 objUser.addUser(stcForm);
13 ColdFusion.Window.hide('addUser');
14 }
1 function delLink()
2 {
3 var selectedRecord = grid.getSelections();
4 var delID = selectedRecord[0].data.ID;
5 if(confirm('Delete User : ' + selectedRecord[0].data.FIRSTNAME))
6 {
7 objUser.delUser(delID);
8 };
9 }
In order to make the calls to the ColdFusion CFC, we use CFAjaxProxy tag. This was a powerful inclusion in ColdFusion 8 allowing us to call CFCs easily in JS. Read more about it at Livedocs. In the demo, we use it to refer to the Users CFC. Then, in the javascript, we also specify the callback and error handlers.
2 {
3 var selectedRecord = grid.getSelections();
4 var delID = selectedRecord[0].data.ID;
5 if(confirm('Delete User : ' + selectedRecord[0].data.FIRSTNAME))
6 {
7 objUser.delUser(delID);
8 };
9 }
1 <cfajaxproxy cfc="UsersD" jsclassname="Users">
2
3 <script>
4 var objUser = new Users();
5 objUser.setErrorHandler(showError);
6 objUser.setCallbackHandler(handleResult);
7 </script>
Now, we can use the objUser JS variable to call CFCs specified in the UsersD CFC.
In the handleResult callback, we refresh the grid. This will refresh our grid data after the CFC functions to add or delete record has been called.
2
3 <script>
4 var objUser = new Users();
5 objUser.setErrorHandler(showError);
6 objUser.setCallbackHandler(handleResult);
7 </script>
1 function handleResult(res)
2 {
3 ColdFusion.Grid.refresh('usersgrid',false);
4 }
The full source code is available Here.
2 {
3 ColdFusion.Grid.refresh('usersgrid',false);
4 }
I will also look at expanding this to implement form validation and form skinning (CSS).
http://www.newebia.co.uk/blog/index.cfm/2009/1/5/C...
That looks great. I like how the ExtJS libraries can be extended easily to add toolbar buttons to the grid.
Currently, I have only played with having the options as form buttons outside the cfgrid, I might look into using the toolbar for the Grid Options as the UI does look good in those screenshots.
http://www.danvega.org/blog/index.cfm/extjs
My code is:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitiona...;
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<cfparam name="usersearchterm" default="">
<script type="text/javascript">
var objUser = new usersClass();
objUser.setErrorHandler(showError);
objUser.setCallbackHandler(handleResult);
function init()
{
grid = ColdFusion.Grid.getGridObject('userSearchResults');
}
function addUser()
{
var objForm = document.addUserForm
var stcForm = {};
stcForm.UserId = objForm.user_id.value;
stcForm.UserTypeId = objForm.user_type_id.value;
stcForm.FirstName = objForm.first_name.value;
stcForm.LastName = objForm.last_name.value;
stcForm.Prefix = objForm.prefix.value;
stcForm.AgeRange = objForm.age_range.value;
stcForm.Gender = objForm.gender.value;
stcForm.Address1 = objForm.address1.value;
stcForm.Address2 = objForm.address1.value;
stcForm.City = objForm.city.value;
stcForm.PostalCode = objForm.postal_code.value;
stcForm.Province = objForm.province.value;
stcForm.Phone1 = objForm.phone_number1.value;
stcForm.Phone2= objForm.phone_number2.value;
stcForm.Phone3 = objForm.phone_number3.value;
stcForm.Country = objForm.country.value;
stcForm.Email = objForm.email.value;
stcForm.Password = objForm.password.value;
objUser.addUser(stcForm);
ColdFusion.Window.hide('adduser');
}
function handleResult(res)
{
ColdFusion.Grid.refresh('userSearchResults',false);
}
function showError()
{
alert("An error occured. Please try again.");
}
function delLink()
{
var selectedRecord = grid.getSelections();
var delID = selectedRecord[0].data.of_user_id;
if(confirm('Delete User : ' + selectedRecord[0].data.name))
{
objUser.delUser(delID);
};
}
</script>
</head>
<body>
<cfajaxproxy cfc="users" jsclassname="usersClass">
<cfajaximport tags="cfform">
<div class="innerWrapper">
<h1>User Administration</h1>
<cfform method="post" action="testing.cfm">
Search users: <cfinput type="text" name="userSearchTerm" value="#userSearchTerm#"> <input type="submit" value="Go">
<cfset newuserwindowid = #createuuid()#>
<cfinput type="button" name="addUserButton" id="addUserButton" value="Add User" onclick="makewindow('adduser','#REQUEST.httppath#views/dspAddUser.cfm','Add a user.')"> <input type="button" id="importUsersButton" value="Import users from file" />
</cfform>
<h2>Search Results</h2>
<cfform>
<cfgrid name="userSearchResults" format="html" bind="cfc:/ofcomponents.users.getusers({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},'#userSearchTerm#')" pagesize="15" width="100%" striperows="yes" striperowcolor="##F5F5F5">
<cfgridcolumn name="of_user_id" display="no">
<cfgridcolumn name="user_id" header="User ID" width="60">
<cfgridcolumn name="name" header="Name" width="200">
<cfgridcolumn name="active" header="Active" width="50">
<cfgridcolumn name="reg_date" header="Reg. Date" width="90">
<cfgridcolumn name="user_type_description" header="User Type" width="150">
<cfgridcolumn name="email" header="E-mail" width="200">
</cfgrid>
</cfform>
<a href="javascript:delLink()">DELETE USER</a>
<cfset ajaxOnLoad("init")>
</div>
</body>
</html>
If anybody can spot the monkey, please let me know!
Filer By: <cfselect id="filtercolumn" name="filtercolumn" bind="cfc:UsersD.getUserColumns()"
display="ColumnName" value="ColumnName" bindOnLoad="true" />
Filter Text: <cfinput type="text" id="filter" name="filter">
<cfinput type="button" name="filterbutton" value="Filter" id="filterbutton"
onclick="ColdFusion.Grid.refresh('usersgrid',false)">
<cfgrid name="usersgrid" pagesize="5" format="html" width="100%" height="200"
bind="cfc:UsersD.getUsers({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},getPageSize(),{filtercolumn},{filter})">
The {filtercolumn} binding means that whenever the selection box is changed, the grid is refreshed. To change the behaviour, you would have to remove the filtercolumn binding from the cfgrid declaration.
You can read more about Binding at Adobe's site:
http://livedocs.adobe.com/coldfusion/8/htmldocs/he...
Thank you so much for your quick reply. I'm new at this and if I can't figure this out soon, then I'm going to have to implement a regular CF search page.. =/
Anyway, If I remove the {filtercolumn} binding nothing happens because the form won't be passing the cfselect value to the CFC when I click on the button. I need to be able to pass the value of the cfselect and cfinput when the user clicks on the button. Otherwise the query won't work.
Thank you so much!
Thanks!
The easiest way to do this would be to bind the cfgrid to a hidden input field. But Do Not bind the hidden input field to the cfselect otherwise when you change the cfselect value, the hidden input field value will also change and the grid will then refresh.
Only change the value of the hidden input field when the user clicks the button, so the button would have an onClick event javascript function that would set the value of the hidden input field to the cfselect value. This way, the cfgrid should only fire when the user clicks the submit button and not when they change the drop-down value. It will also ensure the passing of the cfselect value through the hidden field.
<cfajaxproxy bind="javascript:todetail({files.id@click})" />
The CF Ajax Logger displays this when returning the values from the CFC
info:widget: Firing selection change event for grid id: files
:(