Adobe ColdFusion 8

cfajaxproxy

Description

Creates a JavaScript proxy for a ColdFusion component, for use in an AJAX client. Alternatively, creates a proxy for a single CFC method, JavaScript function, or URL that is bound to one or more control attribute values.

Category

Internet protocol tags

Syntax

<cfajaxproxy
    cfc = "CFC name" 
    jsclassname = "JavaScript proxy class name"> 

OR

<cfajaxproxy
    bind = "bind expression"
    onError = "JavaScript function name"
    onSuccess = "JavaScript function name">

Note: You can specify this tag's attributes in an attributeCollection whose value is a structure. Specify the structure name in the attributeCollection and use the tag's attribute names as structure keys.

See also

DeserializeJSON, IsJSON, SerializeJSON, Using Ajax Data and Development Features in the ColdFusion Developer's Guide

History

ColdFusion 8: Added this tag

Attributes

Attribute

Req/Opt

Default

Description

bind

A bind or cfc attribute is required

 

A bind expression that specifies a CFC method, JavaScript function, or URL to call. For detailed information about specifying bind expressions, see "Binding data to form fields" in the ColdFusion Developer's Guide.

You cannot use this attribute with the cfc attribute.

cfc

A bind or cfc attribute is required

 

The CFC for which to create a proxy. You must specify a dot-delimited path to the CFC. The path can be an absolute filepath, or relative to location of the CFML page. For example, if the myCFC CFC is in the cfcs subdirectory of the ColdFusion page, specify cfcs.myCFC.

On UNIX based systems, the tag searches first for a file whose name or path corresponds to the specified name or path, but is in all lowercase. If it does not find it, ColdFusion then searches for a file name or path that corresponds to the attribute value exactly, with identical character casing.

This attribute cannot be used with the bind attribute.

jsclassname

Optional

The value of the cfc attribute

The name to use for the JavaScript proxy class that represents the CFC.

This attribute cannot be used with a bind attribute.

onError

Optional

 

The name of a JavaScript function to invoke when a bind, specified by the bind attribute fails. The function must take two arguments: an error code and an error message.

This attribute cannot be used with a cfc attribute.

onSuccess

Optional

 

The name of a JavaScript function to invoke when a bind, specified by the bind attribute succeeds. The function must take one argument, the bind function return value. If the bind function is a CFC function, the return value is automatically converted to a JavaScript variable before being passed to the onSuccess function.

This attribute cannot be used with a cfc attribute.

Usage

Make sure that the Enable HTTP Status Codes option on the Server Settings > Settings page of the ColdFusion Administrator is selected. Otherwise, the proxy cannot determine if an error occurs in invoking the CFC function and cannot call the error handler.

A cfajaxproxy tag with a bind attribute does not refresh any control that is not specified in the bind expression.

If you specify a URL in the bind attribute, the HTTP response must consist of a single JSON representation of an object, array, or simple value, corresponding to the onSuccess argument.

Creating a CFC proxy

The cfajaxproxy tag with a cfc attribute generates a JavaScript proxy that represents a CFC on the web client. The tag and the proxy it generates have the following characteristics:

  • The proxy provides one function that corresponds to each CFC remote function. Calling these functions in your client-side JavaScript code remotely calls the CFC functions on the server.
  • The proxy provides several functions that you call to configure the interaction between the client and the server. These functions set the HTTP method and synchronization mode of the XMLHttpRequest call that the proxy uses to interact with the server. The functions also can specify a JavaScript callback handler and an error handler for asynchronous calls.
  • Because JavaScript is case-sensitive, you must ensure that you match the case of the keys in any ColdFusion structure or scope that you send to the client. By default, ColdFusion sets variable names and structure element names to all-uppercase. (You can create structure element names with lowercase characters by specifying the names in associative array notation, for example, myStruct["myElement"]="value".) The keys for the two arrays in the JSON object that the ColdFusion serializeJSON tag generates to represent a query are COLUMNS and DATA, for example, not columns and data.

For detailed information on using AJAX CFC proxies, see "Using ColdFusion Ajax CFC proxies" in "Using Ajax Data and Development Features" in the ColdFusion Developer's Guide.

Note: The proxy passes a _CF_NODEBUG Boolean argument to called CFC functions. ColdFusion checks this value, and when it is true, does not append to the response any debugging information that it normally would send. This behavior ensures that the JSON responses to AJAX requests do include any non-JSON (i.e., debug information) text.

CFC proxy utility functions

When you use the cfc option, the JavaScript proxy object provides the following functions that you can use to control interaction with the server:

Function

Description

setAsyncMode()

Sets the call mode to asynchronous. The calling thread (the Java thread of the client system that is processing the page) is not blocked when you make a call to a proxy function, so page processing can continue while waiting for a response from the server.

The proxy invokes the function specified by the setCallbackHandler function with the response from the server. If an error occurs, the proxy invokes the error handler specified by the setErrorHandler function.

setCallbackHandler(function)

Specifies the callback handler for an asynchronous call. The function parameter is the JavaScript function to invoke as an argument.

The callback function must take one parameter, the return value from the CFC that the proxy has deserialized from JSON to a JavaScript representation.

This method automatically sets the call mode to asynchronous.

setErrorHandler(function)

Sets the error handler that the proxy invokes if there is an error in an asynchronous call. The function parameter is the JavaScript function to invoke.

The error handler function must take two parameters:

  • An HTTP error code
  • A status message

This method automatically sets the call mode to asynchronous.

setForm(ID)

Adds names and values of the fields in the form specified by the ID attribute to the arguments passed by a proxy function that is called immediately after this function.

For more information, see "Submitting data to a CFC" in the ColdFusion Developer's Guide.

setHTTPMethod("method")

Sets the HTTP method to use for the call. The function parameter is a case-insensitive string, and must have one of the following values:

  • GET (the default method)
  • POST

setQueryFormat(format)

Specifies the JSON format in which to return ColdFusion query data. The parameter must have one of the following values:

  • row: (Default) Sends the data as a JSON object with two entries: the column names and an array of row arrays.
  • column: Sends the data as a JSON object that represents WDDX query format. This object has three entries: the number of rows, an array with the column names, and an object where the keys are the column names and the values are arrays containing the column data.

For more information on query formats, see SerializeJSON.

setReturnFormat(format)

Specifies the format in which the CFC function returns the result. ColdFusion automatically converts the function return value into the specified format before returning it to the client.

The parameter must have one of the following values:

  • json (the default format if you don't use this function)
  • plain
  • wddx

If you specify plain, and set the "content-type" header on the response from the server to text/xml, the proxy returns an XML object to the caller or callback function. If the content type is not set to text/xml, the return value from the server is returned as-is.

This function is useful if you return XML or a plain string to the browser.

setSyncMode()

Sets the call mode to synchronous (the default synchronization mode). The calling thread remains blocked until the call returns. If an error occurs, the proxy throws an exception. In synchronous mode, the methods in the CFC proxy return the CFC method results directly to the caller.

Example

The following example uses a remote CFC method to populate a drop-down list of employees. When you select a name from the list, it uses a call to the CFC method to get information about the employee, and displays the results.

The application page has the following lines:

<!--- The cfajaxproxy tag creates a client-side proxy for the emp CFC.
        View the generated page source to see the resulting JavaScript. 
        The emp CFC is in the components subdirectory of the directory that
        contains this page. --->
<cfajaxproxy cfc="components.emp" jsclassname="emp">

<html>
    <head>
        <script type="text/javascript">
        
            // Function to find the index in an array of the first entry 
            // with a specific value.
            // It is used to get the index of a column in the column list.
            Array.prototype.findIdx = function(value){
                for (var i=0; i < this.length; i++) {
                    if (this[i] == value) {
                        return i;
                    }
                }
            }

            // Use an asynchronous call to get the employees for the 
            // drop-down employee list from the ColdFusion server.
            var getEmployees = function(){
                // create an instance of the proxy. 
                var e = new emp();
                // Setting a callback handler for the proxy automatically makes
                // the proxy's calls asynchronous.
                e.setCallbackHandler(populateEmployees);
                e.setErrorHandler(myErrorHandler);
            // The proxy getEmployees function represents the CFC
            // getEmployees function.
                e.getEmployees();
            }
            
            // Callback function to handle the results returned by the
            // getEmployees function and populate the drop-down list.
            var populateEmployees = function(res)
            {
                with(document.simpleAJAX){
                    var option = new Option();
                    option.text='Select Employee';
                    option.value='0';
                    employee.options[0] = option;
                    for(i=0;i<res.DATA.length;i++){
                        var option = new Option();
                        option.text=res.DATA[i][res.COLUMNS.findIdx('FIRSTNAME')]
                            + ' ' + res.DATA[i][[res.COLUMNS.findIdx('LASTNAME')]];
                        option.value=res.DATA[i][res.COLUMNS.findIdx('EMP_ID')];
                        employee.options[i+1] = option;
                    }
                }    
            }

            // Use an asynchronous call to get the employee details.
            // The function is called when the user selects an employee.
            var getEmployeeDetails = function(id){
                var e = new emp();
                e.setCallbackHandler(populateEmployeeDetails);
                e.setErrorHandler(myErrorHandler);
            // This time, pass the employee name to the getEmployees CFC
            // function.
                e.getEmployees(id);
            }
            // Callback function to display the results of the getEmployeeDetails
            // function.
            var populateEmployeeDetails = function(employee)
            {
                var eId = employee.DATA[0][0];
                var efname = employee.DATA[0][1];
                var elname = employee.DATA[0][2];
                var eemail = employee.DATA[0][3];
                var ephone = employee.DATA[0][4];
                var edepartment = employee.DATA[0][5];

                with(document.simpleAJAX){
                    empData.innerHTML = 
                    '<span style="width:100px">Employee Id:</span>' 
                    + '<font color="green"><span align="left">' 
                    + eId + '</font></span><br>' 
                    + '<span style="width:100px">First Name:</span>' 
                    + '<font color="green"><span align="left">' 
                    + efname + '</font></span><br>' 
                    + '<span style="width:100px">Last Name:</span>' 
                    + '<font color="green"><span align="left">'     
                    + elname + '</font></span><br>' 
                    + '<span style="width:100px">Email:</span>'
                    + '<font color="green"><span align="left">' 
                    + eemail + '</span></font><br>' 
                    + '<span style="width:100px">Phone:</span>' 
                    + '<font color="green"><span align="left">' 
                    + ephone + '</font></span><br>' 
                    + '<span style="width:100px">Department:</span>' 
                    + '<font color="green"><span align="left">' 
                    + edepartment + '</font></span>';
                }
            }

            // Error handler for the asynchronous functions.
            var myErrorHandler = function(statusCode, statusMsg)
            {
                alert('Status: ' + statusCode + ', ' + statusMsg);
            }
            
        </script>
    </head>

    <body>
        <!--- The form to display the employee drop-down list and 
        employee data. --->
        <form name="simpleAJAX" method="get">
        List of Employees:&nbsp;&nbsp;&nbsp;
        <select name="employee" onChange="getEmployeeDetails(this.value)">
            <script language="javascript">
                getEmployees();
            </script>
        </select>
        <br><br>
        <span id="empData"></span>
        </form>    
    </body>
</html>

The following component, which gets the data from the data source, must be in a file named emp.cfc in the components subdirectory of the application directory. The CFC uses the cfdocexamples data source that is installed with ColdFusion if you install the documentation.

<cfcomponent>
    <cfset this.dsn = "cfdocexamples">
    <cffunction name="getEmployees" access="remote" returnFormat="json"
            output="false">
        <cfargument name="empid" required="no" type="string" default="0">
        <cfquery name="qryEmp" datasource="#this.dsn#">
            select * from Employees 
            <cfif empid neq 0>
            where Emp_ID = #empid#
            </cfif>
        </Cfquery>
        <cfreturn qryEmp>
    </cffunction>
</cfcomponent>