Using WDDX

The following sections describe how you can use WDDX in ColdFusion applications. The first two sections describe the tools that ColdFusion provides for creating and converting WDDX. The remaining sections show how you use these tools for common application uses.

Using the cfwddx tag

The cfwddx tag can do the following conversions:
From
To
CFML
WDDX
CFML
JavaScript
WDDX
CFML
WDDX
JavaScript

A typical cfwddx tag used to convert a CFML query object to WDDX looks like the following:

<cfwddx action="cfml2wddx" input="#MyQueryObject#" output="WddxTextVariable">

In this example, MyQueryObject is the name of the query object variable, and WddxTextVariable is the name of the variable in which to store the resulting WDDX XML. Note

For more information on the cfwddx tag, see CFML Reference.

Validating WDDX data

The cfwddx tag has a Validate attribute that you can use when converting WDDX to CFML or JavaScript. When you set this attribute to True, the XML parser uses the WDDX DTD to validate the WDDX data before deserializing it. If the WDDX is not valid, ColdFusion generates an error. By default, ColdFusion does not validate WDDX data before trying to convert it to ColdFusion or JavaScript data.

The IsWddx function returns True if a variable is a valid WDDX data packet. It returns False otherwise. You can use this function to validate WDDX packets before converting them to another format. For example, you can use it instead of the cfwddx validate attribute, so that invalid WDDX is handled within conditional logic instead of error-handling code. You can also use it to pre-validate data that will be deserialized by JavaScript at the browser.

Using JavaScript objects

ColdFusion provides two JavaScript objects, WddxSerializer and WddxRecordset, that you can use in JavaScript to convert data to WDDX. These objects are defined in the file webroot/cfide/scripts/wddx.js.

CFML Reference describes these objects and their methods in detail. The example "Transferring data from the browser to the server" shows how you can use these objects to serialize JavaScript to WDDX.

Converting CFML data to a JavaScript object

The following example demonstrates the transfer of a cfquery recordset from a ColdFusion page executing on the server to a JavaScript object that is processed by the browser.

The application consists of four principal sections:

The following example uses the cfsnippets data source that is installed with ColdFusion:

<!--- Create a simple query  --->
<cfquery name = "q" datasource ="cfsnippets">
  SELECT Message_Id, Thread_id, Username, Posted 
  FROM messages
</cfquery>

<!--- Load the wddx.js file, which includes the dump function --->
<script type="text/javascript" src="/CFIDE/scripts/wddx.js"></script>

<script>
  // Use WDDX to move from CFML data to JavaScript
  <cfwddx action="cfml2js" input="#q#" topLevelVariable="qj">
  
  // Dump the recordset to show that all the data has reached 
  // the client successfully.
  document.write(qj.dump(true));
</script>

Note:   To see how cfwddx Action="cfml2js" works, save this code under your webroot directory, for example in wwwroot/myapps/wddxjavascript.cfm, run the page in your browser and select View Source in your browser.

Transferring data from the browser to the server

The following example serializes form field data, posts it to the server, deserializes it, and displays the data. For simplicity, it only collects a small amount of data. In applications that generate complex JavaScript data collections, you can extend this basic approach very effectively. This example uses the WddxSerializer JavaScript object to serialize the data, and the cfwddx tag to deserialize the data.

To use the example:

  1. Save the file under your webroot directory, for example in wwwroot/myapps/ wddxserializedeserialze.cfm.
  2. Display http://localhost/myapps/wddxserializedeserialze.cfm in your browser.
  3. Enter a first name and last name in the form fields.
  4. Click Next.

    The name appears in the Names added so far box.

  5. Repeat steps 3 and 4 to add as many names as you wish.
  6. Click Serialize to serialize the resulting data.

    The resulting WDDX packet appears in the WDDX packet display box. This step is intended only for test purposes. Real applications handle the serialization automatically.

  7. Click Submit to submit the data.

    The WDDX packet is transferred to the server-side processing code, which deserializes it and displays the information.

<!--- load the wddx.js file --->
<script type="text/javascript" src="/CFIDE/scripts/wddx.js"></script>

<!--- Data binding code --->
<script>

  // Generic serialization to a form field
  function serializeData(data, formField)
  {  
    wddxSerializer = new WddxSerializer();
    wddxPacket = wddxSerializer.serialize(data);
    if (wddxPacket != null)
    {
      formField.value = wddxPacket;
    }
    else
    {
      alert("Couldn't serialize data");
    }
  }
  
  // Person info recordset with columns firstName and lastName
  // Make sure the case of field names is preserved
  var personInfo = new WddxRecordset(new Array("firstName",
  "lastName"), true);

  // Add next record to end of personInfo recordset
  function doNext()
  {
    // Extract data
    var firstName = document.personForm.firstName.value;
    var lastName = document.personForm.lastName.value;
    
    // Add names to recordset
    nRows = personInfo.getRowCount();
    personInfo.firstName[nRows] = firstName;
    personInfo.lastName[nRows] = lastName;
    
    // Clear input fields
    document.personForm.firstName.value = "";
    document.personForm.lastName.value = "";
    
    // Show added names on list
    // This gets a little tricky because of browser differences
    var newName = firstName + " " + lastName;
    if (navigator.appVersion.indexOf("MSIE") == -1)
    {
      document.personForm.names[length] = 
        new Option(newName, "", false, false);
    }
    else
    {
      // IE version
      var entry = document.createElement("OPTION");
      entry.text = newName;
      document.personForm.names.add(entry);
    }

  }

</script>


<!--- Data collection form ---> 
<form action="#cgi.script_name#" method="Post"
name="personForm">

  <!--- Input fields --->
  Personal information<br>
  First name: <input type=text name=firstName><br>
  Last name: <input type=text name=lastName><br>
  <br>
  
  <!--- Navigation & submission bar --->
  <input type="button" value="Next" onclick="doNext()">
  <input type="button" value="Serialize"
  onclick="serializeData(personInfo, document.personForm.wddxPacket)">
  <input type="submit" value="Submit">
  <br><br>
  Names added so far:<br>
  <select name="names" size="5">
  </select>
  <br>
  
  <!--- This is where the WDDX packet will be stored --->
  <!--- In a real application this would be a hidden input field. --->
  <br>
  WDDX packet display:<br>
  <textarea name="wddxPacket" rows="10" cols="80" wrap="Virtual">
  </textarea>
  
</form>


<!--- Server-side processing --->
<hr>
<b>Server-side processing</b><br>
<br>
<cfif isdefined("form.wddxPacket")>
  <cfif form.wddxPacket neq "">

    <!--- Deserialize the WDDX data --->
    <cfwddx action="wddx2cfml" input=#form.wddxPacket#
    output="personInfo">

    <!--- Display the query --->
    The submitted personal information is:<br>
    <cfoutput query=personInfo>
      Person #CurrentRow#: #firstName# #lastName#<br>
    </cfoutput>
  <cfelse>
    The client did not send a well-formed WDDX data packet!

  </cfif>
<cfelse>
  No WDDX data to process at this time.
</cfif>

Storing complex data in a string

The following simple example uses WDDX to store complex data, a data structure that contains arrays as a string in a client variable. It uses the cfdump tag to display the contents of the structure before serialization and after deserialization. It uses the HTMLEditFormat function in a cfoutput tag to display the contents of the client variable. The HTMLEditFormat function is required to prevent the browser from trying to interpret (and throwing away) the XML tags in the variable.

<!--- Enable client state management --->
<cfapplication name="relatives" clientmanagement="Yes">

<!--- Build a complex data structure --->
<cfscript>
  relatives = structNew();
  relatives.father = "Bob";
  relatives.mother = "Mary";
  relatives.sisters = arrayNew(1);
  arrayAppend(relatives.sisters, "Joan");
  relatives.brothers = arrayNew(1);
  arrayAppend(relatives.brothers, "Tom");
  arrayAppend(relatives.brothers, "Jesse");
</cfscript>

A dump of the original relatives structure:<br>
<br>
<cfdump var="#relatives#"><br>
<br>

<!--- Convert data structure to string form and save it in the 
      client scope --->
<cfwddx action="cfml2wddx" input="#relatives#" output="Client.wddxRelatives">


The contents of the Client.wddxRelatives variable:<br>
<cfoutput>#HtmlEditFormat(Client.wddxRelatives)#</cfoutput><br>
<br>


<!--- Now read the data from client scope into a new structure --->
<cfwddx action="wddx2cfml" input="#Client.wddxRelatives#" output="sameRelatives">

A dump of the sameRelatives structure <br>
generated from client.wddxRelatives<br>
<br>
<cfdump var="#sameRelatives#">

Comments