This is the third in a short series of blog entries demonstrating one way to use ColdFusion's built in Ajax code to load detail information into a form. I've written two previous entries (linked to below) and I recommend checking them out first if you have not done so already. The first entry simply bound a text field to a back end CFC. When you typed in a number the code would attempt to retrieve the complete record from the server. The second entry modified the code to use a button to perform the database lookup. This final entry (heh, I hope, the original author keeps asking for interesting tweaks!) modifies the code yet again. Now it provides a loading message while the data is being retrieved. The code isn't terribly different from before so I'll paste in the entire thing and then explain the modifications.
<cfajaxproxy bind="javascript:getData({mybutton@click})">
<cfajaxproxy cfc="test" jsclassname="dataproxy">
<script>
function getData() {
document.getElementById("loading").innerHTML="Loading..."
var artid = ColdFusion.getElementValue("artid")
if(isNaN(artid)) return
dataService.getData(artid)
}
function showData(d) {
document.getElementById("loading").innerHTML=""
//convert into a struct
var data = {}
for(var i=0; i < d.COLUMNS.length; i++) {
data[d.COLUMNS[i]] = d.DATA[0][i]
}
document.getElementById('artname').value = data["ARTNAME"]
document.getElementById('description').value = data["DESCRIPTION"]
document.getElementById('price').value = data["PRICE"]
}
var dataService = new dataproxy()
dataService.setCallbackHandler(showData)
</script>
<div id="loading"></div>
<cfform>
id: <cfinput type="text" name="artid" id="artid"> <cfinput type="button" name="mybutton" value="Lookup"><br/>
name: <cfinput type="text" name="artname" id="artname" readonly="true"><br/>
description: <cftextarea name="description" id="description" readonly="true"></cftextarea><br/>
price: <cfinput type="text" name="price" id="price" readonly="true"><br/>
</cfform>
The first modification is a simple one - adding a loading div. It will only be used for status messages as data is being fetched. The getData() method was then modified to change the innerHTML of the div and place a loading message. You could easily use one of those fancy animated gear-type GIFs as well. Lastly, showData was modified to remove the loading message.
That's it - and I hope these examples are helpful. I've been using jQuery so much I feel pretty rusty with the ColdFusion built-in Ajax stuff.
Archived Comments
Do you think you might be able to add the JQuery alternative too please?
Here's a fun little AJAX gif creator.
http://www.ajaxload.info/
I normally don't like it when people post large text blocks in a comment, but since its my blog, I'm allowed to be a hypocrite. ;)
<script src="http://ajax.googleapis.com/..."></script>
<script>
$(document).ready(function() {
$("#mybutton").click(function() {
$("#loading").html("Loading....")
var artid = $("#artid").val()
if(isNaN(artid)) return
$.getJSON("test.cfc?method=getdata&artid=" + artid + "&returnformat=json", {}, function(d,status) {
$("#loading").html("")
var data = {}
for(var i=0; i < d.COLUMNS.length; i++) {
data[d.COLUMNS[i]] = d.DATA[0][i]
}
$("#artname").val(data["ARTNAME"])
$("#description").val(data["DESCRIPTION"])
$("#price").val(data["PRICE"])
})
})
})
</script>
<div id="loading"></div>
<form>
id: <input type="text" name="artid" id="artid"> <input type="button" id="mybutton" value="Lookup"><br/>
name: <input type="text" name="artname" id="artname" readonly="true"><br/>
description: <textarea name="description" id="description" readonly="true"></textarea><br/>
price: <input type="text" name="price" id="price" readonly="true"><br/>
</form>
Hi Ray
Just wondering on your thoughts of using cfajaxproxy vs jquery method.
From my testing Ajaxproxy, sprydataset & CFFORM generate alot of script ininline in the page. I dont mind CF creating script for me, but why cant it write an external JS file rather than inline script ?
To your first point: It depends. :)
cfajaxproxy, and other CF-built in features, are typically very easy to use. So if you aren't very comfortable with JS then I'd probably always recommend using them. For me, I'm (slowly) getting more comfortable with JS, so I prefer jQuery.
To your second point: Remember that the JS is a combination of static libraries and dynamic code. It wouldn't make sense for the dynamic code to be saved to the file system just for one request.
fair call.
we currently use prototype/scriptaculous for most of our JS work. Im able to make OO based classes and completely unobtusive javascript which i can then gzip (via CF/java) and set all the correct HTTP headers (using combine.cfc) to fully optimise for the best YSlow ratings.
These are my main problem with the inline script CF generates.
1 - it breaks unobtrusive principles
2 - its not optimal in terms of performance. ie if i have the same 'AutoCompleter' on 2 pages the user must download all the required JS twice.
May I ask you how do you realize this for CF7 ?
Cound this be a Ask-a-Jedi-ColdFusion-Ajax-example-of-retrieving-fields-of-data-4 ? -)
Thank you,
Michel
The one I posted in the comments, the one in jQuery, would work perfectly, except that the call to the CFC would not work. In CF7, a CFC can return WDDX or XML, not JSON. So instead, you would point to a CFM. That CFM would run the CFC and would convert the data to JSON. If you google for json coldfusion, you will find the JSON component. I forget who made it - but I use the same component in LighthousePro.
@Ray, it is http://www.epiphantastic.co... by Jehiah & Thomas
Yep.
Is it possible to pop up a window that requests the information (which I know is possible) but then updates the information on the page that pop'd the window?
I'm guessing as I try to figure this all out, it's somehow in the window's onHide() that another call is made to the server for the final information.
lol, ok, I know it is, but how - because this pop-up comment page, is a pop-up, and as soon as I click post the main page was updated, how?
Found your post here, http://www.coldfusionjedi.c... I'm sure it'll be enough