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:
<form>
number one: <input type="text" name="one" id="one"><br>
number two: <input type="text" name="two" id="two"><br>
</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:
<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.
function doAddPost() {
We need to know where we will be posting the form, so next I define the URL:
var 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:
var one = $("one").value;
Then I'll grab the value from the second form field:
var 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:
var formData = 'one='+one+'&two='+two;
Next I encode any values in the string, like spaces or other special characters:
formData = 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.
Spry.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:
function doAddPost() {
var url = "moon.cfm";
var one = $("one").value;
var two = $("two").value;
var formData = 'one='+one+'&two='+two;
formData = encodeURI(formData);
Spry.Utils.loadURL('POST', url, true, resFunc, {postData: formData, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-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:
<cfsetting enablecfoutputonly=true>
<cfparam name="form.one" default="0">
<cfparam name="form.two" default="0">
<cfif isNumeric(form.one) and isNumeric(form.two)>
<cfoutput>#form.one+form.two#</cfoutput>
<cfelse>
<cfoutput>0</cfoutput>
</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:
function resFunc(request) {
var result = request.xhRequest.responseText;
$("result").innerHTML = "Result was: " + result;
}
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:
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;
}
formData = encodeURI(formdata);
Spry.Utils.loadURL('POST', url, true, resfunc, {postData: formdata, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});
}
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:
<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.
Archived Comments
Thank you sooooo much Ray, I look forward to more :) I'm printing and putting the jug on now.
Putting the jug on?
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.
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?
This sample code only works with text fields. I'm going to update it eventually to work with all form fields.
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.
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.co...
Hope it could help
Massimo
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/spr... (underneath the large photo.
But how can I display the actual result????
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.
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?
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();
}
I think if you want to do this you need to store it in a global javascript variable.
But in your example it isn't in a global javascript variable.
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.
I am trying to do exactly what you illustrate in
http://ray.camdenfamily.com...
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.
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
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
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?
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??
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?
=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?
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.
test
No, its not that, by know i made some progress
there is the source: http://www.wl.com.br/spryXM...
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!
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...
Thanks again Ray and Massimo, you guys are the best!
You might check out the Spry.Utils.submitForm function. It grabs all of the form variables and submits very nicely.
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.co...
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 :-)
Thanks - yea - I definitely recommend submitForm now. This post is rather old. :)
@MF - Did you report the bug?
Yes, I reported the bug
@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
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. ;)