Twitter: raymondcamden


Address: Lafayette, LA, USA

Doing form Post in Spry (2)

01-29-2007 10,403 views ColdFusion 31 Comments

Last week or so I blogged about doing form postings with Spry. I was asked to provide a bit more documentation so I thought I'd show a slightly more detailed example.

First lets start with a very simple form:

view plain print about
1<form>
2number one: <input type="text" name="one" id="one"><br>
3number two: <input type="text" name="two" id="two"><br>
4</form>

This form has two simple text fields named one and two. I want to use Spry to send the values of these two fields to the server. First lets add a simple button:

view plain print about
1<input type="button" value="Add" onClick="doAddPost()">

This simply fires off a JavaScript function. I'm going to break the function up and explain each and every line to make it as clear as possible. First, start the function.

view plain print about
1function doAddPost() {

We need to know where we will be posting the form, so next I define the URL:

view plain print about
1var url = "moon.cfm";

Now I need to grab the values I want to post. Normally with a submit button you don't have to worry about this. The browser simply sends all the form fields. In this case though I have to specify the fields manually. First I'll grab the value of the form field, one, using the Spry/Prototype $() shortcut:

view plain print about
1var one = $("one").value;

Then I'll grab the value from the second form field:

view plain print about
1var two = $("two").value;

The form post data must be sent like a query string: foo1=value1&foo2=value2. Again, I have to do this by hand:

view plain print about
1var formData = 'one='+one+'&two='+two;

Next I encode any values in the string, like spaces or other special characters:

view plain print about
1formData = encodeURI(formData);

So the last thing we do is run the Spry code that will handle the form post. I talked about this more in the last post so I won't spend a lot of time on it.

view plain print about
1Spry.Utils.loadURL('POST', url, true, resFunc, {postData: formData, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});

The first argument defines the type of request (GET or POST). The second argument is the URL value I defined earlier. The third argument defines if the call is asynchronous or not. The fourth argument defines a function to run with the result of the HTTP call. Lastly there is a structure of arguments that define the request. Again I have to thank Keith for figuring this out.

So here is the function again all in one code block:

view plain print about
1function doAddPost() {
2    var url = "moon.cfm";
3    var one = $("one").value;
4    var two = $("two").value;    
5    var formData = 'one='+one+'&two='+two;
6    formData = encodeURI(formData);
7    Spry.Utils.loadURL('POST', url, true, resFunc, {postData: formData, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});
8}

So how do we handle this server side? We have a few options. As I mentioned, the loadURL function lets you define code to run with the result. So whatever the server returned I can work with in JavaScript. This can be either a string or XML or WDDX. To make it easier I'll just return a simple string:

view plain print about
1<cfsetting enablecfoutputonly=true>
2<cfparam name="form.one" default="0">
3<cfparam name="form.two" default="0">
4
5<cfif isNumeric(form.one) and isNumeric(form.two)>
6    <cfoutput>#form.one+form.two#</cfoutput>
7<cfelse>
8    <cfoutput>0</cfoutput>
9</cfif>

Obviously there isn't anything too complex here, just the addition of two numbers. I take the result and simply output it directly to the client requesting the data. With me so far?

Now let's return to JavaScript and work with the result. I had specified the a function named resFunc would handle the result. The function is all of 4 lines:

view plain print about
1function resFunc(request) {
2    var result = request.xhRequest.responseText;
3    $("result").innerHTML = "Result was: " + result;    
4}

Spry automatically passes a collection of data back. The information I'm interested in resides in xhRequest.responseText. Once I have that, I can write out the result in the browser.

So I had mentioned more than once I wanted to make this process a bit simpler. Here is my first draft at it:

view plain print about
1function doFormPost(url,formlist,resfunc) {
2    var formdata = '';
3    var formarray = formlist.split(',');
4    for(var i=0; i < formarray.length; i++) {
5        formdata+='&'+formarray[i]+'=';
6        var fValue = $(formarray[i]).value;
7        formdata+=fValue;
8    }
9    formData = encodeURI(formdata);
10    Spry.Utils.loadURL('POST', url, true, resfunc, {postData: formdata, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});
11}

This lets you pass in a url and a list of form fields to post. The third argument is optional. So to do a Spry post you can do this instead of the button and custom function I had before:

view plain print about
1<input type="button" value="Add3" onClick="doFormPost('moon.cfm', 'one,two',resFunc)">

As I said though this is just a first draft. Right now it assumes just text fields.

31 Comments

  • Mark #
    Commented on 01-30-2007 at 3:49 AM
    Thank you sooooo much Ray, I look forward to more :) I'm printing and putting the jug on now.
  • Commented on 01-30-2007 at 5:32 AM
    Putting the jug on?
  • Commented on 01-30-2007 at 7:57 AM
    Hmmmmmm.... jug... last time I heard someone "putting the jug on" they were placing it under the spigot of a STILL!!! (grins)

    Anyway... nice stuff, Ray... between Spry and Flex2 my brain has been pretty stuffed the last few weeks. I HATE being behind the learning curve.
  • Mark #
    Commented on 01-30-2007 at 12:51 PM
    Now now, no still here lol. I'm in New Zealand so I guess it's a saying we have that you folk don't. It means I'm boiling some water for a cup of coffee or tea :) Nothing sinister, I promise.

    Thanks again Ray, you are a life saver. Before I try, will this pass multiple checked check boxes to coldfusion the normal way?
  • Commented on 01-30-2007 at 1:10 PM
    This sample code only works with text fields. I'm going to update it eventually to work with all form fields.
  • Mark #
    Commented on 01-30-2007 at 6:14 PM
    Ray, Thanks to your tutorial and a little googling, I got this puppy working, it's made my day.

    // delete images action function
    function deleteImages() {
    var url = "img-del.cfm";
    var vaultImgFile = document.imgForm.vaultImgFile;
        var formData = "vaultImgFile=";
           for (i = 0; i < vaultImgFile.length; i++){
          if (vaultImgFile[i].checked == true){
             formData = formData + vaultImgFile[i].value + ",";
          }//ends IF
       }//ends FOR
       // strip last comma
       formData = formData.substr(0,formData.length-1);
       // encode for spry
    formData = encodeURI(formData);
    Spry.Utils.loadURL('POST', url, true, delComplete, {postData: formData, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});
    }
    function delComplete(request) {
       var result = Spry.Utils.encodeEntities(request.xhRequest.responseText);
       $("respContent").innerHTML = "Result was: " + result;
       // reset status text area
       setTimeout("clearVaultImageResults()",10000);
       // reload image list
       dsVaultImages.setURL("images.cfm?nocache="+d.getSeconds());
       dsVaultImages.setXPath('images/image');
       dsVaultImages.loadData();
    }

    Cheers.
    Mark.
  • Commented on 01-30-2007 at 11:30 PM
    Extract form field value this way can be time consuming. That's why I wrote a JavaScript library for forms that, among other features, let you extract and "serialize" field's value from any form. You can see it in action here
    http://www.massimocorner.com/libraries/form/sample...

    Hope it could help

    Massimo
  • Commented on 02-16-2007 at 6:21 PM
    Excellent!!!

    I can understand it all but for one part that will be obvious to anyone with a brain and knowledge of Java,

    "Spry automatically passes a collection of data back. The information I'm interested in resides in xhRequest.responseText. Once I have that, I can write out the result in the browser."

    HOW to I display the reasult?

    I have it all working
    see http://www.coolabah.com/spry/demos/gallery/test.cf... (underneath the large photo.

    But how can I display the actual result????
  • Commented on 02-16-2007 at 7:56 PM
    There are a few ways to display something. One way is like so:

    Assume foo is the id of a div:

    <div id="foo"></div>

    Then in JS you can do:

    var mydiv = document.getElementById("foo");
    mydiv.innerHTML = "some stirng";

    This will write out some string as the contents of the div.
  • Commented on 02-16-2007 at 8:14 PM
    OK. I think I'm missing something.

    On my page I have these functions as per your example
    function doFormPost(url,formlist,resfunc) {
    var formdata = '';
    var formarray = formlist.split(',');
    for(var i=0; i < formarray.length; i++) {
    formdata+='&'+formarray[i]+'=';
    var fValue = $(formarray[i]).value;
    formdata+=fValue;
    }
    alert(formdata);
    formData = encodeURI(formdata);
    Spry.Utils.loadURL('POST', url, true, resfunc, {postData: formdata, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});
    }
    function resFunc(request) {
    var result = request.xhRequest.responseText;
    $("result").innerHTML = "Result was: " + result;



    }


    doFormPost is called onclick.

    Given THAT code, how do I display "result?
  • Commented on 02-17-2007 at 6:32 PM
    OK I have figured it out to an extent. BUT I'm having trouble with the last parameter of Spry.Utils.loadURL.

    In the code snippet below I am trying to pass a value to Spry.Utils.loadURL that will them be passed to resfunc as request. But I cannot work out how to do this.

    The function that calls Spry.Utils.loadURL works ok., I test that it is receiving the correct value by using alert(value). But how do I get this value into the argument list of Spry.Utils.loadURL so I can display it?


    function doFormPost(url,photoId,resfunc) {
    formData = encodeURI(photoId);
    Spry.Utils.loadURL('POST', url, true, resfunc, {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"});

    }



    function resFunc(request) {
    var mydiv = document.getElementById("foo");
    var result = request.xhRequest.responseText;
    $("result").innerHTML = "Result was: " + result ;
    mydiv.innerHTML = result;



    }


    function HandleThumbnailClick(id, photoId)
    {

    StopSlideShow();
    doFormPost('moon.cfm', photoId,resFunc);
    dsPhotos.setCurrentRow(id);
    ShowCurrentImage();
    }
  • Commented on 02-17-2007 at 9:42 PM
    I think if you want to do this you need to store it in a global javascript variable.
  • Commented on 02-17-2007 at 10:00 PM
    But in your example it isn't in a global javascript variable.
  • Commented on 02-17-2007 at 10:11 PM
    I must be misunderstanding you. You want to do a form post, and when you, remember a value such that when the form post is done you can retrieve it. Is that not true.
  • Commented on 02-17-2007 at 10:25 PM
    I am trying to do exactly what you illustrate in
    http://ray.camdenfamily.com/index.cfm/2007/1/29/Do...

    but instead of passing a form variable, I'm trying to post an argument to the function .

    I'm concerned with thew last argument -
    {postData: formData, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}}

    where I do not have "formdata", but a variable passed to the function.
  • Commented on 02-17-2007 at 10:37 PM
    formdata is simply a query string I build manually of form values. You can use other values instead, like the one you passed in. But it must be in query string form:

    name=value&name=value& etc
  • Commented on 02-17-2007 at 10:57 PM
    I'm sorry, but I don't understand.

    In function doFormPost(url,photoId,resfunc) {
    formData = encodeURI(photoId);
    Spry.Utils.loadURL('POST', url, true, resfunc, {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"});

    }

    How do I pass the contents of photoId
  • Commented on 02-17-2007 at 11:13 PM
    You have a few issues here. First, you didn't follow what I said about name=value (query string) format. You can't just pass a value like photoid. It MUST look like a query string. So if you want to pass photoId, you have ot pass a name for the value as well:

    var formData = 'photoId='+photoId;

    This says - pass the value photoId, but also give it a name of photoId. In your CFM code that processes this form post, you would use form.photoID.

    Then you must encode the value:

    formData = encodeURI(formData);

    Lastly, you removed the part of loadURL that contained formData:

    Spry.Utils.loadURL('POST', url, true, resFunc, {postData: formData, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});

    See how I pass formData as the value to postData?
  • Commented on 04-23-2007 at 10:40 AM
    A liked your post, its almost what im looking for, maybe you can help-me

    I need to send post params.

    I can send using this for example:
    var dsPhotos = new Spry.Data.XMLDataSet("/photos.php", "/gallery/photos/photo", { method: "POST", postData: "galleryid=2000&offset=20&limit=10", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" } });

    Using post data it works,ok, or i can send using your example too, ok, it works.

    But in my aplication a create a spry DataSet, and i dont trigger onload, i do that after a few actions.

    So, i need to send a post params after i create the Dataset, because i use DataSet.loadData() after some time

    But, your example should work, but i couldant populate a spry dataset with my xml result format

    Could you help me??
  • Commented on 04-23-2007 at 10:55 AM
    I'm sorry, but I'm having a hard time understanding your English. Everything after "But in my ..." is a bit greek to me. Can you reword?
  • Commented on 04-23-2007 at 12:27 PM
    =D=D=D=D

    Really sory, let´s try again

    I need to send post params.

    I can send using this for example:
    var dsPhotos = new Spry.Data.XMLDataSet("/photos.php", "/gallery/photos/photo", { method: "POST", postData: "galleryid=2000&offset=20&limit=10", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" } });

    Using post data it works,ok, or i can send using your example too, ok, it works.


    My problem is:
    I dont know hot set Post Params, after define a spry DataSet
    ex:
    var myDs = new Spry.Data.XMLDataSet()
    function triggerLater(){
    myDs.setXPath("Node/ChildNode")
    myDs.setURL(myxml.aspx?aLotOfParams=somevalue);
    myDs.loadData()
    }

    those params ('aLotOfParams') must be POST, because they have a lot of info.

    But in your example we heve that function:
    function resFunc(request) {
    var result = request.xhRequest.responseText;
    $("result").innerHTML = "Result was: " + result;
    }

    than ok, i receive my xml, and i can see it, but i need to populate it in my spry data set
    Somethink like:

    function resFunc(request) {
    var result = request.xhRequest.responseText;
    mySpryDataSet=request
    }

    if you have time,could you help me?
  • Commented on 04-23-2007 at 1:18 PM
    So are you saying, how do I do a post after my spry data is loaded? If so you simply need to use a dataset observer. The docs cover this and show you how you could run X after data has been loaded.
  • Marcelo Macedo #
    Commented on 04-25-2007 at 7:21 AM
    test
  • Commented on 04-25-2007 at 7:25 AM
    No, its not that, by know i made some progress

    there is the source: http://www.wl.com.br/spryXMLv2.zip

    So, i have problems to parse my xml data, it works fine in firefox, but not in ie6, do you know why?

    Another thing, i just could use it in Firefox when i removed all the white spaces from my XML, Is there some way to keep using spaces??

    Thanks for your help!
  • Commented on 12-15-2007 at 1:45 PM
    Ray, this is a great post, thank you for it!

    I went ahead and modified the example slightly and incorporated Massimo's serializer with it. If anyone is interested in downloading the example, please go to:

    http://blog.webexterminator.com/index.cfm/2007/12/...

    Thanks again Ray and Massimo, you guys are the best!
  • Commented on 06-07-2008 at 7:39 PM
    You might check out the Spry.Utils.submitForm function. It grabs all of the form variables and submits very nicely.
  • Commented on 06-08-2008 at 1:16 AM
    Spry.Utils.submitForm is a better solution since it handles <select>, radion buttons and checkboxes too. Just be aware it has a bug, it doesn't properly handles <select> tags whenever their value is an empty string. You can see it in action here:

    http://www.massimocorner.com/spry/extractParamsFro...

    On a side note, Prototype is affected by a similar bug. Actually, it's worst, since it returns different value for IE and FF. At least Spry is wrong, but consistent :-)
  • Commented on 06-08-2008 at 10:03 AM
    Thanks - yea - I definitely recommend submitForm now. This post is rather old. :)

    @MF - Did you report the bug?
  • Commented on 06-08-2008 at 2:52 PM
    Yes, I reported the bug
  • MikeG #
    Commented on 12-01-2008 at 4:15 PM
    @Ray
    Realizing that this is an OLD post, when I tried to implement I found that you may need to update this line:

    First I'll grab the value of the form field, one, using the Spry/Prototype $() shortcut:

    To:
    First I'll grab the value of the form field, one, using the Spry Spry.$() shortcut:

    The updated versions of the js files no longer support just $(), it is now Spry.$() - or atleast, by changing from $() to Spry.$() it worked
  • Commented on 12-01-2008 at 4:36 PM
    Good point. I'm feeling a bit lazy though so I assume folks will scan the comments. :) I've got way too many blog posts to make a habit out of updating them all. ;)

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty