Arnkrishn
Arnkrishn

Reputation: 30414

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.

Upvotes: 14

Views: 29662

Answers (6)

TRubel
TRubel

Reputation: 3

Using a ColdFusion variable in JavaScript is powerful! Be sure to use

<cfoutput> var #toScript(ColdFusionVAR, 'javascriptVar')# </cfoutput>

You can now reference your variable as javaScriptVar using CFAJAXPROXY

Be sure to include this in your template

<head> 
<cfajaxproxy cfc="cfc.yourclassname" jsclassname="jsCFCclassName">
</head>

Using your class on the JavaScript side.

You would us it like so.

var JS_CFC_Obj;

JS_CFC_Obj = new jsCFCclassName()

You can now make calls to functions inside of that cfc.

jsCFCclassName.functionName(javascript var);

Upvotes: 0

Henry
Henry

Reputation: 32885

You may try <cfajaxproxy> tag in CF8 if you like.

Upvotes: 1

Kung Fu Ninja
Kung Fu Ninja

Reputation: 3752

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

Upvotes: 9

Adam Tuttle
Adam Tuttle

Reputation: 19804

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>

Upvotes: 16

antony.trupe
antony.trupe

Reputation: 10824

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');

Upvotes: 17

razzed
razzed

Reputation: 2683

You don't necessarily need to use "AJAX" (the XML part, specifically), but you can use a remote server call:

$.get('/execute-function.cfm?func=whatever', function (result) { $('#result').html(result); });

Really depends on what you need to do with the result. The above code will place the HTML result in a div on your page:

<div id="result"></div>

You could use an asynchronous call and parse XML, but I've found that I rarely need either.

Upvotes: 3

Related Questions