Invoke ColdFusion function using AJAX

I need to invoke a ColdFusion function(present in a .cfm file) when the user clicks on a link. And I would like to do it using jQuery. I have a jQuery snippet which looks like-

<script type="text/javascript">
$(document).ready(function(){
       $("td.ViewLink a").click(function(event){
         event.preventDefault();

)}

I am new to both jQuery and AJAX, so I might sound naive here. Should I use AJAX to invoke the ColdFusion function? Something like requesting to execute a specific function on the server.

Any help in this regard is appreciated.

Cheers.


If you have multiple functions in your cfm(even if you don't), put them in a cfc. Then you can use the following url pattern to invoke a specific method.

cfc named myEntityWS.cfc

<cfcomponent>
  <cffunction name="updateDescription" access="remote" returntype="string">
    <cfargument name="value" type="string" required="yes">
    <cftry>
      your code here
    <cfcatch>
      <cfoutput>
        #cfcatch.Detail#<br />
        #cfcatch.Message#<br />
        #cfcatch.tagcontext[1].line#:#cfcatch.tagcontext[1].template#
      </cfoutput>
    </cfcatch>
    </cftry>
  </cffunction>
</cfcomponent>

Javascript

$.get('myEntityWS.cfc?method=updateDescription&value=someValue');

You can't do exactly what you're trying to in your example code. You have a few options, though.

Method 1: Remotely accessible object

Move your function(s) into a CFC, and access them via the URL of the CFC. This access method requires that the function use the permission attribute access='remote' -- if set to public (the default) or private, (or package, or any role levels, etc) then you'll get a method not found error when attempting to access it remotely.

Doing this, you're creating a SOAP webservice and consuming it via AJAX. You do this by using the following format in your jQuery request:

http://domain.com/path/to/your.cfc?method=functionName&argument1=arg1Val&foo=bar&...

If you have ColdFusion 8, you can also specify the returnFormat='format' url argument, which will convert whatever native ColdFusion data objects you return to the requested format on the fly. It supports JSON, XML, and WDDX.

foo.cfc

<cfcomponent output="false">
  <cffunction name="foobar" output="false" access="remote" hint="...">
    <cfargument name="arg1" type="string" required="true" />
    ...
    <cfreturn someVar />
  </cffunction>
</cfcomponent>

Access by URL:

http://domain.com/path/to/foo.cfc?method=foobar&arg1=some%20value&returnFormat=JSON



Method 2: Remote proxy object

The negative side of approach #1 is that there is a slight efficiency hit on instantiating CFCs, so if this particular AJAX method will be run very frequently, and/or your CFC contains more than a few methods or is longer than a couple hundred lines, you don't want to instantiate it over and over for every request. Instead, you would want to look into the remote proxy pattern, where you cache the CFC that implements the functionality in Application scope, and have a separate 'remote proxy' CFC that is much lighter-weight, and simply acts as a proxy (hence the name) between the http request and the cached CFC.

In this pattern, your business object (the one that has the function that does the real work) can have access=public (or package, etc), as long as the proxy has access to it. The proxy itself must have access=remote, though.

proxy.cfc

<cfcomponent output="false">
  <cffunction name="foobar" output="false" access="remote" hint="...">
    <cfargument name="arg1" type="string" required="true" />
    <!--- Application.foo is an instantiated object of foo.cfc --->
    <cfreturn Application.foo.foobar(argumentCollection=arguments) />
  </cffunction>
</cfcomponent>

Access by URL:

http://domain.com/path/to/proxy.cfc?method=foobar&arg1=some%20value&returnFormat=JSON



Method 3: Do It Yourself

Lastly, you could manually implement the function invocation and return in a CFM template. This method doesn't involve the (slight) performance hit of writing a CFC, but will be more typing for you, and additional potential points of failure. To do this, include your functions in the CFM template, and treat the output stream as just that: a stream of text that will be returned to the browser.

You should be careful to manage whitespace in the return value (use output=false on function definitions, consider using <cfsetting enableCFOutputOnly='true', and just be careful about your spacing overall). If your jQuery request expects JSON back, you need to serialize it. (If you need to serialize data to JSON on ColdFusion 6 or 7, I recommend JSONUtil)

With this approach, you point your AJAX request to the .cfm file with URL parameters, and then you need to write code that takes those url parameters and passes them into the function, and then displays (essentially, returns to the AJAX request) the result of the function.

foo.cfm

<cfsetting enableCFOutputOnly="true">
<cfparam name="arg1" default="defaultVal"/>

<cffunction name="foobar" output="false" access="remote" hint="...">
  <cfargument name="arg1" type="string" required="true" />
  ...
  <cfreturn someVar />
</cffunction>

<cfset variables.result = foobar(url.arg1) />
<cfoutput>#serializeJSON(variables.result)#</cfoutput>

Just saw this post. I am using a cfc and jquery ajax to display bunch of calculated values. My cfc has the following:

<cfcomponent output="true">
<cfscript>
    this.init();
</cfscript>
     <cffunction name="init" access="public" returntype="any">
       <cfset variables.dsn = application.dsn>
        <cfreturn variables.dsn> 
     </cffunction>
     <cffunction name="getFinanceTerms" access="remote" output="true" returntype="void">
         <cfargument name="sales_price" type="numeric" required="yes">
         <cfargument name="interestRate" type="numeric" required="yes">
           <!--- some calculations here --->
         #arguments.salesPrice# <!--- just to have something displayed --->
         <cfreturn>
     </cffunction>
 </cfcomponent>

I use JQuery.ajax:

  $.ajax({
      type:"POST",
      url:"financeTerms.cfc?method=getFinanceTerms",
      data: "sales_price=55000&interestRate=5.99",
      cache:false,
      success: function(msg) {
      $("#someDiv").html(msg);
      }
  });

Perhaps, it will be useful to somebody else...