Archive for December, 2007

Toggle state of a db record with cfajaxproxy

I’m really getting into the AJAX thing now with CF8 and tweaking my Admin apps to make them more user-friendly and avoid big page reloads.

Many of my database tables have an isActive field to determine whether a record should appear on the public site. Until now I’ve relied on users editing the entire record to set the state of this but if you’ve got a few updates to do you soon get dizzy going between lists and forms and keeping track of where you’re up to. For me, this is where AJAX can make a big difference.

The following example might not be perfect but it gives an idea of what’s possible.

1. The JS stuff

Being a fusebox user, I have this in a single generic fuse that I can use with any page. We create the Javascript proxy to the CFC and then write a couple of JS functions to handle the asynchronous call and response.

<!--- Create a JS proxy for our component --->
<cfajaxproxy cfc="components.ajaxToggleActive" jsclassname="ajaxToggle" />

<script type="text/javascript">
	//<![CDATA[
	function toggleState( table, id ) {
		//Set table cell to ... to show it's in progress
		var displayState = document.getElementById('active_' + id);
		displayState.innerHTML = '...';

		//Call component to toggle state
		var t = new ajaxToggle();
		t.setCallbackHandler( toggleResult );
		t.change( table, id );
	}

	function toggleResult( response ) {
		//Set table cell to represent new state
		var displayState = document.getElementById( 'active_' + response.ID );
		displayState.innerHTML = ( response.STATE == 1 ? 'Yes' : 'No' );
	}
	// ]]>
</script>

2. In the table cell

In the record list, display page, or wherever, we just need to call the toggleState function. Note also the a tag has an id attribute so we can change the content of it with JS.

<a href="javascript:toggleState('vehicle','#rsData.id#')" id="active_#rsData.id#">#YesNoFormat( rsData.isActive )#</a>

3. The CFC

This CFC just has the one method to toggle the status of an isActive field in the specified table.

<cfcomponent output="false">

	<cffunction name="change" output="false" access="remote">
		<cfargument name="table" default="" />
		<cfargument name="id" default="" />

		<cfset var rsState = "" />
		<cfset var result = StructNew() />

		<!--- Toggle field --->
		<cftry>
			<cfquery datasource="#application.dsn#">
				UPDATE
					#arguments.table#
				SET
					isActive = 1 - isActive
				WHERE
					id = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.id#" />
			</cfquery>

			<!--- Check user exists --->
	 		<cfquery name="rsState" datasource="#application.dsn#">
				SELECT
					isActive
				FROM
					#arguments.table#
				WHERE
					id = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.id#" />
			</cfquery>

			<cfset result = { id = arguments.id, state = rsState.isActive } />

			<cfcatch />
		</cftry>
		<cfreturn result />
	</cffunction>

</cfcomponent>

4. The Result

Toggle Active Your users can simply click the Yes/No option to switch items on and off without lots of page loads.


cfajaxproxy returning ColdFusion structures

I’ve been tinkering with cfajaxproxy recently to pimp up some of the pages in an Admin application. One thing I couldn’t figure out was how to access a returned ColdFusion structure in Javascript. However, as with most things, it’s easy if you know the answer… all struct keys become UPPERCASE !

e.g.

<cfreturn { id = arguments.id, state = rsState.isActive } />

In javascript would be:

alert( myVar.ID + ' ' + myVar.STATE );

Maybe it’s just me that didn’t realize this, but I haven’t read it in the CF Docs anywhere :-S