Creating a jQuery AJAX form with Coldfusion

Posted on Friday, November 20th, 2009 at 8:43 am

Although submitting a form via ajax is probably not a good idea in many cases, there are some cases where it might serve a purpose.  Forms on the web seem to be trending towards simplicity.  In the case that you’re working with a very simple form, like the one I’m using here (name, email, and comments), using a form that submits with AJAX as opposed to running through the server might be useful.  I’ve personally never used this, but was playing around with it and decided to post what I have in case anyone else is interested.  Pushing forward then.

This is what our form will do.  A user fills it out and clicks submit.  The form submits with AJAX (no page refresh) to a coldfusion component.  From there the data is stored in a database and emailed to the owner of the form.  This really isn’t that complicated, but several files are involved so I’ll run through those here.  Also for the sake of simplicity I’ve got all of our files in the same directory, but for the sake of organization you may consider a different directory structure.

1. formHTML.cfm (contains the html form)

2. formCFC.cfc (contains the methods to record data to database and email data)

3. formJS.js (contains the jquery to submit the form and return our success message)

The HTML (formHTML.cfm)

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”><!— create a proxy to call our cfc methods —>
<cfajaxproxy cfc=”formCFC” jsclassname=”formData”>

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
<title>Our Form</title>

<!– LOAD IN THE JQUERY LIBRARY –>
<script src=”jquery.js” type=”text/javascript”></script>
<!– LOAD IN THE FORM SUBMIT JS –>
<script src=”formJS.js” type=”text/javascript”></script>
</head>

<body>
<div id=”container”>
<form name=”contact” method=”post”>
Name:
<input type=”text” name=”userName”><br />
Email:
<input type=”text” name=”userEmail”><br />
Comments:
<textarea name=”userComments”></textarea><br />

<input type=”button” name=”userSubmit” value=”Submit”>
</form>
</div>
</body>
</html>

I’ve included the entire HTML here since it’s fairly brief. A few important things to point out. At the top of the page we create a proxy using the cfajaxproxy tag.  This allows us a way (a very simple way) to call Coldfusion functions in an external component with javascript.  Also in the head we include the jquery file (in production you might want to use the minimized version) and the formJS.js file that contains the javascript we write to make this work.  And lastly, in our body we have our form.  But notice that there is no action attribute in the opening form tag.  This is because we are not submitting our page to the server.  Also the submit button is type ‘button’ and not ‘submit’ as is usual.  Again because our page isn’t going anywhere.  Let’s take a look at our javascript now.

The Javascript (formJS.js)

$(document).ready(function()
{
$(“input[name='userSubmit']“).click(function()
{
//call a function to submit the form data
submitForm();
});
});

submitForm = function()
{
var username = $(“input[name='userName']“).val();
var useremail = $(“input[name='userEmail']“).val();
var usercomments = $(“textarea[name='userComments']“).val();

//create a new instance of our proxy
var submission = new formData();

//set the handler to refresh the grid when the function has been run successfully
submission.setCallbackHandler(verifySubmission);

//set the error function in case the function does not run correctly
submission.setErrorHandler(errorHandler);

//call the method via the proxy
submission.initSubmit(username, useremail, usercomments);
}

verifySubmission = function(resp)
{
if(resp === true)
{
$(“#container”).slideUp(“slow”, function()
{
$(“#container”).html(“”);
$(“#container”).html(“Thank You!!”);
$(“#container”).slideDown(“slow”);
});

}
else
{
alert(“Failed”);
}
}

//this function will return the error that occurs, if on occurs
errorHandler = function()
{
//alert the user of the error
alert(statusCode + ‘: ‘ + statusMsg);
}

We have four functions here.  We open the script with the classic jQuery $(document).ready() that runs the code after the page has loaded.  When this runs it initializes a function that listens for when the input button named ‘userSubmit’ is clicked.  When it is clicked it runs a function called ‘submitForm’.  What we have so far is when a user clicks the submit button our javascript is calling the ‘submitForm’ function.

The ‘submitForm’ function is where the good stuff happens.  First thing we need to do is get the values contained in the form that the user is wanting to submit.  Our three form values are held in the vars ‘username’, useremail’, and ‘usercomments’.  The next four things we do in this function is running our Coldfusion component.  If you remember we had a <cfajaxproxy> tag in our HTML that called our component and had a ‘jsclassname’ of ‘formData’.  This class name is what we will use to create a new instance of our proxy.  We create this new instance by setting a var equal to a ‘new formData()’.  Next we create two handler functions.  First is the ‘setCallbackHandler’ function.  Into this we pass the name of the function we want to run after we have successfully run the function in our component.  Next is the ‘setErrorHandler’ function.  Into this we pass the name of the function we want to run if an error occurs during the processing.  And lastly, we make the actual call to our Coldfusion component.  I’ll explain more in a moment, but for right now I’ll say that in our CFC we have a function called ‘initSubmit’ that takes three arguments: ‘username’, ‘useremail’, ‘usercomments’.  This will call our component, pass the arguments, and wait for the return data.

When the data is returned the function name passed into the setCallbackHandler function will run, if successful.  Let’s take a look at this function.  Again for right now our component is passing back ‘true’ if our database and email were updated and sent successfully, and ‘false’ if not.  So I’m checking if our form was submitted successfully or not.  You’ll notice that when we create our ‘verifySubmission’ function we pass into it ‘resp’.  This represents the data that is passed back from our Coldfusion component.  So, since I’m passing back a boolean I check if ‘resp’ is equal to ‘true’.  If not I create a simple alert that says failed. If successful I get all jQuery fancy with animations and stuff since jQuery is just so freakin’ easy.  Quick explanation is that our form in the HTML is wrapped in a div with an id of ‘container’.  We use jQuery to slide this div up and hide it.  Once hidden, I set the HTML in the div to nothing, and then set the HTML to a simple ‘Thank You’.  I then slide the div back down to reveal our ‘Thank You’ message.  See a demo of how this works here. (This demo doesn’t submit anything.)

Lastly, we have the errorHandler function that runs if there is an error processing.  Here I just have an alert that tells the status and message.  Now let’s take a look at our CFC and see what is happening when the javascript calls our ‘initSubmit’ function.

The Component (formCFC.cfc)

<cfcomponent displayname=”Record Form Data” hint=”Submits the form data to the database and email.” output=”false”>

<!— ********************************  INITIALIZE FORM SUBMISSION  ******************************** —>
<cffunction name=”initSubmit” displayname=”Initialize Submission” description=”Initializes the form submission process to the database and email.” access=”remote” output=”false” returntype=”boolean”>

<!— PASS IN THE FORM DATA —>
<cfargument name=”username” displayName=”User Name” type=”string” hint=”Name of the user submitting the form.” required=”true” />
<cfargument name=”useremail” displayName=”User Email” type=”string” hint=”Email of the user submitting the form.” required=”true” />
<cfargument name=”usercomments” displayName=”User Comments” type=”string” hint=”Comments left by the user filling out the form.” required=”true” />

<!— create a success var —>
<cfset VARIABLES.success = true>

<!— SEND DATA TO BE RECORDED IN DATABASE —>
<cfset VARIABLES.dataRecorded = recordSubmission(ARGUMENTS.username, ARGUMENTS.useremail, ARGUMENTS.usercomments)>

<cfswitch expression=”#VARIABLES.dataRecorded#”>
<cfcase value=”true”>
<!— SEND DATA TO BE EMAILED —>
<cfset VARIABLES.dataEmailed = emailSubmission(ARGUMENTS.username, ARGUMENTS.useremail, ARGUMENTS.usercomments)>

<cfswitch expression=”#VARIABLES.dataEmailed#”>
<cfcase value=”false”>
<cfset VARIABLES.success = false>
</cfcase>
</cfswitch>
</cfcase>

<cfdefaultcase>
<cfset VARIABLES.success = false>
</cfdefaultcase>
</cfswitch>

<!— return our success var —>
<cfreturn VARIABLES.success>

</cffunction>

<!— ********************************  RECORD SUBMISSION IN DATABASE  ******************************** —>
<cffunction name=”recordSubmission” displayname=”Record Data Submission” description=”Records the form submission data to the database.” access=”private” output=”false” returntype=”boolean”>

<!— PASS IN THE FORM DATA —>
<cfargument name=”username” displayName=”User Name” type=”string” hint=”Name of the user submitting the form.” required=”true” />
<cfargument name=”useremail” displayName=”User Email” type=”string” hint=”Email of the user submitting the form.” required=”true” />
<cfargument name=”usercomments” displayName=”User Comments” type=”string” hint=”Comments left by the user filling out the form.” required=”true” />

<!— create a success var —>
<cfset VARIABLES.success = true>

<!— open a transaction —>
<cftransaction action=”begin”>
<cftry>
<!— RECORD DATA —>
<cfquery name=”VARIABLES.recordData” datasource=”datasource”>
INSERT INTO form_test_tbl (form_test_name, form_test_email, form_test_comments)
VALUES (<cfqueryparam value=”#ARGUMENTS.username#” cfsqltype=”cf_sql_varchar”>,
<cfqueryparam value=”#ARGUMENTS.useremail#” cfsqltype=”cf_sql_varchar”>,
<cfqueryparam value=”#ARGUMENTS.usercomments#” cfsqltype=”cf_sql_varchar”>)
</cfquery>

<!— commit the transaction —>
<cftransaction action=”commit” />

<!— catch any errors —>
<cfcatch type=”database”>
<cfset VARIABLES.success = false>
<cftransaction action=”rollback” />
</cfcatch>
</cftry>
</cftransaction>

<!— return our success var —>
<cfreturn VARIABLES.success>

</cffunction>

<!— ********************************  EMAIL SUBMISSION  ******************************** —>
<cffunction name=”emailSubmission” displayname=”Email Form Submission” description=”Emails the form submission data to the owner.” access=”private” output=”false” returntype=”boolean”>

<!— PASS IN THE FORM DATA —>
<cfargument name=”username” displayName=”User Name” type=”string” hint=”Name of the user submitting the form.” required=”true” />
<cfargument name=”useremail” displayName=”User Email” type=”string” hint=”Email of the user submitting the form.” required=”true” />
<cfargument name=”usercomments” displayName=”User Comments” type=”string” hint=”Comments left by the user filling out the form.” required=”true” />

<!— create a success var —>
<cfset VARIABLES.success = true>

<!— EMAIL DATA —>
<cfprocessingdirective suppresswhitespace=”false”>
<cftry>
<cfmail to=”yourname@yourdomain.com” from=”contact@yourdomain.com” subject=”You have been contacted” type=”html”>
Name: #ARGUMENTS.username#<br />
Email: #ARGUMENTS.useremail#<br />
Comments: #ARGUMENTS.usercomments#
</cfmail>

<!— catch any errors —>
<cfcatch type=”any”>
<cfset VARIABLES.success = false>
</cfcatch>
</cftry>
</cfprocessingdirective>

<!— return our success var —>
<cfreturn VARIABLES.success>

</cffunction>

</cfcomponent>

I’ve included the entire component here.  It has three functions: ‘initSubmit’, ‘recordSubmission’, and ‘emailSubmission’.  I’ll start with the ‘initSubmit’ function.  First we pass in our three arguments, which is our form data being passed in from the javascript.  We set a success var to return.  If all goes well it will return true, and if not false.  This is the boolean value we check for in our javascript function ‘verifySubmission’.

Notice that our ‘initSubmit’ function here has it’s access set to ‘remote’.  This allows our form to be a web service, but it’s most likely that you don’t want this form to be used as such. However, to use it with <cfajaxproxy> it has to have its access set to ‘remote’.  So if you use this in production you may want to consider some form of security.  Honestly, this is a pretty big topic that has books written on it.

First we send our form data to the ‘recordSubmission’ function.  Here we use <cftransaction> and <cftry> tags to manage our database interaction.  We try to insert our form data into our database, if it works we commit the transaction, if not we catch the error and roll back the transaction.  Also keep in mind that I’ve just made up a database here, but if you are using this you will need to change the SQL statement to reflect your database.

So going back to our ‘initSubmit’ function, we now check if our data was inserted into the database successfully.  If not we set our success var to false and return it.  If so we run the ‘emailSubmission’ function.  Here we just use a <cftry> tag and <cfmail> to send the form data to whomever it should be sent to.  If there is an error submitting the email we return ‘false’ to the ‘initSubmit’ function, but if successful we return ‘true’.

Once again, back at our ‘initSubmit’ function, we check if our email was sent successfully, and if so we return true to our javascript where we come full-circle.  The javascript will now process our returned boolean, and if ‘true’ we’ll get the ‘Thank You’ message, and if not an alert telling us it was a catastrophic failure.

Maybe Adri can follow this post up with some CSS for our form and a post on how she did so, since my form is a little hard on the eyes.  Stay tuned.

Tags ,
CategoryColdfusion
2 Responses to “Creating a jQuery AJAX form with Coldfusion”
  1. susan says:

    interesting

  2. Chris Keeler says:

    What is the form is in a query cfoutput and you get multiple forms on a single page. The data submitted to the JQuery is always the first row’s data. How can you tell the JQuery to make the forms unique? Thanks.
    -CK

Leave a Reply

*
(Won't be published) *