Using AJAX with Model-Glue

I've had to use AJAX (specifically Spry) now with two Model-Glue sites, so I thought I'd share how I've done it. This isn't rocket science per se, but I'm pretty happy with my method and I thought others might like to see it as well. (And the flip side is that if I'm doing something totally stupid, folks will let me know pretty quickly.)

First - let me start with the basics. Any page using Spry will need to:

  • Include the Spry libraries
  • Load the XML data

Let me first talk about how I included the Spry libraries. I could have simply included the libraries in my layout view. However, the Spry libraries aren't the skinniest files around, so I didn't want to do that. What I've done is simply tell the viewState when to load Spry. So if a page needs Spry, I'll do this:

<cfset viewState.setValue("useajax", true)>

My layout view then does:

<cfset useajax = viewState.getValue("useajax", false)> ..... <cfif useajax> <script type="text/javascript" src="/js/xpath.js"></script> <script type="text/javascript" src="/js/SpryData.js"></script> </cfif>

For those who don't quite know Model-Glue, all this means is that by default, the Spry libraries will not be loaded. A view has to be explicitly state that it wants to load them.

The next thing I need to do is load the XML. Here is one sample of doing that using Spry:

var dsIssues = new Spry.Data.XMLDataSet("#viewState.getValue("myself")#xml.issues", "issues/issue");

Note the use of Model-Glue syntax to construct the URL. I also decided that all XML based events will be named xml.something. In this case, xml.issues. Now let's look at the event definition:

<event-handler name="xml.issues"> <broadcasts> <message name="GetIssues" /> <message name="ToXML"> <argument name="viewstatekey" value="issues" /> <argument name="xmlpath" value="issues/issue" /> </message> </broadcasts> <views> <include name="body" template="xml.view.cfm" /> </views> <results/> </event-handler>

What's going on here? First I have my generic call to get my data. In this case, it is GetIssues. This is going to fetch a query of data. Now for the cool part. The ToXML message is how I convert the query to XML. I pass in the viewstatekey. This is simply telling the method where to look for data. In this case the value is issues, meaning that GetIssues set it's data in a key named issues. Next I pass in the xmlpath that should be used when creating the XML.

What all of this means is - I can use ToXML in multiple places by simply telling it where the data is and how to construct the XML. It is a generic event that can be used for multiple Spry events. The view (xml.view.cfm) simply returns the XML:

<cfsetting enablecfoutputonly=true>

<cfset xml = viewState.getValue("xml")>

<cfcontent type="text/xml"><cfoutput>#xml#</cfoutput>

<cfsetting enablecfoutputonly=false>

In case you are wondering, the code that creates the XML is simply my ToXML cfc (which will hopefully have a proper project page soon). This is how it was done in the controller:

<cffunction name="toXML" access="public" returnType="void" output="true"> <cfargument name="event" type="any"> <cfset var viewKey = arguments.event.getArgument("viewstatekey")> <cfset var xmlpath = arguments.event.getArgument("xmlpath")> <cfset var xmlroot = listFirst(xmlPath, "/")> <cfset var xmlchild = listLast(xmlPath, "/")> <cfset var data = "">
&lt;cfif arguments.event.valueExists(viewkey)&gt;
	&lt;cfset data = arguments.event.getValue(viewkey)&gt;
	&lt;cfset xmlData = variables.xmlCFC.queryToXML(data, xmlroot, xmlchild)&gt;

&lt;cfset arguments.event.setValue("xml", xmldata)&gt;	


As you can see, nothing too fancy here. The main thing to note is how it was built in a generic fashion.

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate. He focuses on JavaScript, serverless 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