Doing form Post in Spry (2)
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.
Comments
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.
Thanks again Ray, you are a life saver. Before I try, will this pass multiple checked check boxes to coldfusion the normal way?
// 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.
http://www.massimocorner.com/libraries/form/sample...
Hope it could help
Massimo
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????
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.
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?
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();
}
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.
name=value&name=value& etc
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
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?
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??
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?
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!
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!
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 :-)
@MF - Did you report the bug?
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

