A reader pinged me last night with a relatively simple request:
I want a dropdown and when the user changes the value, I want to use Ajax to hit a CFC and do something with the result.
This is incredibly trivial, but I thought it might be kind of fun to share the code as I write it. Normally I make a demo and share the final bits, but perhaps it would useful to folks to see how I build things like this.
As I said, this is super trivial, but even when I'm doing simple stuff, I'll build up the bits in steps and check in the browser to ensure I'm not making any stupid mistakes. With that in mind, let's get started.
First, I built an HTML template.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
})
</script>
</head>
<body>
<form>
<select id="options">
<option>--</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
</form>
<div id="result"></div>
</body>
</html>
The important bits are:
- I chose jQuery for my Ajax, DOM manipulation library and put in an empty ready block. As I said, I take things in steps, so there isn't any JavaScript code written yet.
- I added a dropdown. I know I'm going to be listening for changes to the dropdown so I gave it an ID. There are 3 values, but the first one simply reflects a null state.
- The reader wants to display the result so I've added a blank div. Again though, I'm sure to include an ID value so I can access it from jQuery.
Next - I'm going to add code to listen for the dropdown change. This code block, and the rest, are within the document ready block and I won't be showing the entire file. At the very end I'll share the template.
$("#options").change(function(e) {
var selected = $(this).val();
console.log('change:', selected);
});
Nothing scary here - just listen for the change, get the selected value, and log it to the console. This is all jQuery 101 stuff, but yes, I do stuff like this and run it in the browser just to be sure. I code fast, and I can alt-tab/alt-r quickly, so this doesn't take me long, but as I tend to screw things up quite a bit I like to build out in steps.
Ok, so the next part involves taking the value and sending it to ColdFusion to do something. The actual server-side logic isn't important here. For now the logic will be to take the value passed and return it preprended with, "I was sent: ".
Here is the component for that logic. I wrote this in script form but you could use tags. But don't. Seriously.
<pre
component {
url.returnformat="json";
remote function doStuff(required string input) { return "I was sent: #arguments.input#"; }
}
I'm assuming this is self-explanatory, except for perhaps the url.returnformat line. That lets me skip passing JSON as a returnformat to the query string when using the API. What we really need (and I'll go file a bug report) is a way to specify a default returnformat at the application level. WDDX was cool ten years ago but there is no reason it should be the default now - backwards compat or not. You can do a default returnformat per method, but that gets messy. To confirm it worked, I opened it up in my browser directly: http://localhost:8501/testingzone/ddajax/api.cfc?method=dostuff&input=foo
Ok, so now back to the JavaScript. All we need to do is run an XHR against the CFC and put the response in the div:
$result = $("#result");
$("#options").change(function(e) {
var selected = $(this).val();
console.log('change:', selected);
if(selected === '--') return;
$.get("api.cfc?method=dostuff", {input:selected}, function(res) {
$result.html(res);
},"JSON");
});
The first change is to cache the result div selector. Since I'll be updating it multiple times (well, if the user makes multiple changes) it makes sense to grab it once. The next change is to use $.get to fetch the data. We could have use $.getJSON too. Finally, we take the result and place it in the div. (Note - we are using JSON to wrap a string which is overkill. We could have used the 'plain' returnformat value as well. I expect that for most folks they will be returning 'data' not just strings so I kept the code as you see to better reflect a real use case.)
And that's it. Not exactly rocket science, but there you go. Here is the complete HTML file.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$result = $("#result");
$("#options").change(function(e) {
var selected = $(this).val();
console.log('change:', selected);
if(selected === '--') return;
$.get("api.cfc?method=dostuff", {input:selected}, function(res) {
$result.html(res);
},"JSON");
});
})
</script>
</head>
<body>
<form>
<select id="options">
<option>--</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
</form>
<div id="result"></div>
</body>
</html>