jQuery Does Not Post Undefined Values In AJAX Requests

Posted February 8, 2011 at 10:40 AM by Ben Nadel

Tags: ColdFusion, Javascript / DHTML

NOTE: The original premise of this post was WRONG. I talked about NULL values, but demonstrated "undefined" values. This only applies to Undefined values!! Thanks to Justice for this critical catch!!

When you trigger an AJAX request in jQuery, you have the option to supply a "data" object with the request. This data object contains a collection of key-value pairs that get posted as individual form (or url) parameters. There is a small feature of the AJAX request model that took me a little while to get used to; but, now that I understand it, I completely love to use it. What I'm referring to is the fact that Undefined values are not posted during an AJAX request.

To demonstrate what I'm talking about, take a look at the following jQuery page:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Undfined Values And AJAX Requests</title>
  • <script type="text/javascript" src="../jquery-1.4.4.js"></script>
  • </head>
  • <body>
  •  
  • <h1>
  • Undefined Values And AJAX Requests
  • </h1>
  •  
  • <form>
  •  
  • <input type="submit" value="Post AJAX" />
  •  
  • </form>
  •  
  • <div id="results" style="margin-top: 30px ;">
  • <!--- This is where we'll post the AJAX response. --->
  • </div>
  •  
  •  
  • <!--- ------------------------------------------------- --->
  • <!--- ------------------------------------------------- --->
  •  
  •  
  • <script type="text/javascript">
  •  
  • // Create an object to hold a number of values that we are
  • // going to be posting to the AJAX request handler.
  • var clientSideData = {
  • a: 1,
  • b: 2,
  • z: 3
  • };
  •  
  •  
  • // Now, bind to the form to trap the submission and handle it
  • // via an AJAX request.
  • $( "form" ).submit(
  • function( event ){
  •  
  • // Prevent the default form submission.
  • event.preventDefault();
  •  
  • // Now, post varaibles to the request handler.
  • //
  • // NOTE: As we do this, some of the values we pass
  • // will exist, some will not.
  • $.ajax({
  • type: "post",
  • url: "./handler.cfm",
  • data: {
  • a: clientSideData.a,
  • b: clientSideData.b,
  • c: clientSideData.c,
  • x: clientSideData.x,
  • y: clientSideData.y,
  • z: clientSideData.z
  • },
  • dataType: "html",
  • success: function( html ){
  •  
  • // Dump the response into the page.
  • $( "#results" ).html( html );
  •  
  • }
  • });
  •  
  • }
  • );
  •  
  • </script>
  •  
  • </body>
  • </html>

At the top of my Javascript, you'll notice that I am defining a client-side data structure with a few properties. Then, when I go to trigger my AJAX request, you can see that I am posting both defined (a, b, z) and undefined (c, x, y) properties from said data structure. Now, rather than passing c, x, and y as Undefined values or some sort of empty string or falsey value, jQuery simply ignores them.

To illustrate this, my AJAX request handler - handler.cfm - echoes its own FORM scope:

handler.cfm

  • <!--- Set the response type. --->
  • <cfcontent type="text/html" />
  •  
  • <!---
  • Simply CFDump out the FORM post values so that we show the
  • client which form variables were passed with the AJAX request.
  • --->
  • <cfdump
  • var="#form#"
  • label="Form Post"
  • />

And, when we make the AJAX request, we can clearly see that our undefined values are neither posted to the handler nor echoed back in the response:

 
 
 
 
 
 
UNDEFINED Values Do Not Get Passed Along With A jQuery AJAX Request. 
 
 
 

At first, this might feel weird; after all, if you tell jQuery to post something, shouldn't it at least try to post the Key? Once you get used to this concept, however, it becomes really nice to work with. Take, for example, something like the Javascript Geolocation API. When you work with geolocation and the browser, the user has the opportunity to deny geolocation access; and, even if access is granted, there is a chance that the browser won't be able to determine the proper location.

This means that if you need to post geolocation information back to the server, there's a chance that no location information will be available. You could use some complex client-side logic to dynamically build your AJAX data object based on the information that is available; or, you could just post NULL values and live hassle-free.

  • // Default the location to a undefined coordinate set. This way, we
  • // have a constant data structure.
  • var location = {};
  •  
  •  
  • // -- Get geolocation... code not shown. Will update the
  • // -- the location data struct once latitude and longitude
  • // -- become available.
  •  
  •  
  • // Post location to the server. It may be UNDEFINED.
  • $.ajax({
  • ...
  • data: {
  • latitude: location.latitude,
  • longitude: location.longitude
  • }
  • ...
  • });

Here, you can see that the location information starts off as undefined coordinate values that may or may not be updated over time. Then, when we go to post the location, we simply post the local coordinates, not taking into account whether or not they are defined. We leave the "checking" up to jQuery and allow our client-side code to remain as simple as possible.

I know this is just a tiny feature of the jQuery AJAX request model; but, it is a feature that I have come to really like. And, as your client-side code starts to become more robust, the chances that you'll post Undefined values to the server definitely go up. It's nice to know that jQuery doesn't require us to worry about the insignificant details.




Reader Comments

Feb 8, 2011 at 11:01 AM // reply »
11 Comments

Hey Ben,

What do you use to annotate your screenshots?


Feb 8, 2011 at 11:04 AM // reply »
10,743 Comments

@Anthony,

I just take a screenshot and mark it up in Adobe Fireworks.


Feb 8, 2011 at 11:33 AM // reply »
148 Comments

There's a plugin for Chrome that allows you to do this as well. Here it is:

https://chrome.google.com/extensions/detail/alelhddbbhepgpmgidjdcjakblofbmce


Feb 8, 2011 at 11:35 AM // reply »
148 Comments

Not sure if the Chrome version can do the Console (if that exists for this browser), though.


Feb 8, 2011 at 11:43 AM // reply »
10,743 Comments

@Lola,

In Firefox, I have a great extension called "ScreenGrab!". It allows you take a screen shot not just of the visible screen, but also of the entire web page (below the fold of the window).

For things like this, though, where I need to get the Console in the picture, I just the OS native functionality. On Mac, I'm rocking SHIFT+CTRL+CMD+3 (that's a finger-twister for you!).


Feb 8, 2011 at 12:06 PM // reply »
211 Comments

@Anthony: Ben draws all the pretty pink lines and text himself. ;)


Feb 8, 2011 at 12:33 PM // reply »
113 Comments

@Ben,

Note that in the sample code with screenshot, you did not include *null* values. You included *undefined* values. These are two very different things in JavaScript. In the example of clientSideData.c, c is undefined. What happens if you set clientSideData.c = null (rather than undefined, i.e., setting a value of null to that key rather than never having set any value at all to that key) and then attempt the POST with jQuery?

Cheers,
Justice


Feb 8, 2011 at 12:36 PM // reply »
260 Comments

Hi @Ben.

Did you notice that AJAX was rewritten from the ground up in jQuery 1.5? Since you used 1.4.4 in your experiment above, you might want to download 1.5 and see if its behavior is upward compatible.

We have 1.5, but the behavior above doesn't change how we have to code. Our callbacks are generally to look up a hand-entered Zip code or NAICS code in a text box, for example. In other words, this.form.Zip.value could be the nullstring, which makes it defined, which means we have to code cfif IsDefined ("URL.Zip") and (Len(URL.Zip) gt 0) anyway.

P.S.: Pre-OS-X slang calls Shift-Command-digit utilites FKEYs. The full screen grab is called FKEY 3, for example. You can also (minimally) annotate your screen grabs in Preview. You can also crop in Preview via select, copy, New from Clipboard. In a pinch, these techniques can be used on any OS X Mac, where you can't necessarily control what 3rd party software is installed.


Feb 8, 2011 at 12:40 PM // reply »
10,743 Comments

@Justice,

Hmmm, crap, you're right :( In the middle of a meeting - will clarify afterward. I think I made a big mistake here :)


Feb 8, 2011 at 1:02 PM // reply »
10,743 Comments

@Justice,

You are right, by the way; null values get converted to the string, "null" and undefined values get ignored... still in my meeting, but this makes the post mostly irrelevant.

I swear I thought I have tested this. But, I suppose that I do typically use this with undefined values.

Will update shortly.


Feb 8, 2011 at 1:22 PM // reply »
10,743 Comments

@Todd,

Pink for the win!!

@Justice,

The post has been updated. Your eagle-eye has once again proved immensely valuable. Thanks for getting my back!

@WebManWalking,

Yeah, I typically have to add some sort of server-side check like isNumeric(). I also use CFParam to default values when acceptable.


Feb 8, 2011 at 3:28 PM // reply »
1 Comments

Does this still strictly identical with jQuery 1.5 and its AJAX module rewrited or some changes has been made ?


Feb 8, 2011 at 3:30 PM // reply »
10,743 Comments

@Pomeh,

I have not had a chance to play with jQuery 1.5 just yet. I think the changed made to $.ajax() in 1.5 had more to do with multiple handler assignments and assignment after-the-fact. I am not sure than any core "behavior" has changed.


Feb 8, 2011 at 5:17 PM // reply »
260 Comments

http://blog.jquery.com/2011/01/31/jquery-15-released/


Feb 8, 2011 at 10:54 PM // reply »
10,743 Comments

@WebManWalking,

I'm especially interested in the Deferred stuff. I know very little about that and am curious to see what the buzz is about. In my Seven Languages book, they sometimes talked about things called, Futures, which were results that had not been created yet; but, that kind of stuff was happening at the language level.


Feb 9, 2011 at 12:34 PM // reply »
260 Comments

@Ben,

It's easy to confuse null and undefined if you're a ColdFusion or Java developer. You've already written on that similarity in ColdFusion. Consider also a HashMap in Java:

  • HashMap hm = new HashMap();
  • hm.put("key", "value");
  • ...
  • hm.put("key", null); // Don't need it anymore.
  • ...
  • String getNullOne = hm.get("key");
  • String getNullTwo = hm.get("undefinedkey");

Once the values have been moved out to Strings, how do you distinguish getNullOne from getNullTwo? You don't. They both contain null, getNullOne because that's what got put to it and getNullTwo because the key was never defined.

Of course, you can define an Iterator over hm and discover defined keys that way. Or you can call hm.containsKey(). But after the values are moved out to Strings, they're both null and indistinguishable.

So don't beat yourself up too excessively over null versus undefined. Common problem.


Feb 12, 2011 at 7:15 PM // reply »
54 Comments

I didn't find this problem. It's probably only related to POST requests. I will check further when I have a server to see if things came through.

var data = {
a: 1,
b: 2};
jQuery.ajax({
url:'http://www.bennadel.com/',
type: 'post',
dataType: "html",
data:{
a: data.a,
b: data.b,
c: data.c
}
});
---Firebug output---
Parametersapplication/x-www-form-urlencoded
a 1
b 2
c undefined
Source
a=1&b=2&c=undefined

jQuery version 1.3.1 (firebug on your site)


Feb 17, 2011 at 10:39 AM // reply »
10,743 Comments

@WebManWalking,

I appreciate the support - I feel like I was just being sloppy :) It's ok though, onward and upward!

@Drew,

On my testing server, I am getting the same behavior (undefined not passed) using either the GET or POST approaches. But, this blog was probably tested in jQuery 1.4.x and the local testing I just did was on jQuery 1.5. Perhaps it was a behavior they added later on?


Feb 17, 2011 at 10:51 AM // reply »
54 Comments

@Ben, I checked on jsFiddle. This started after 1.3.2, this behavior occurred in 1.4.2 and 1.4.4. I'm going through their changelog/bugs and see if this is intended behavior or a regression.


Feb 17, 2011 at 10:54 AM // reply »
10,743 Comments

@Drew,

Nice detective work, and excellent use case for jsFiddle! I have to believe that this is the intended behavior; I can't think of a reason why an "undefined" value would want to get passed through.


Feb 17, 2011 at 11:16 AM // reply »
54 Comments

//This is totally false, strict JSON parsing is on the return not the request. I have no idea why this changed in 1.4. https://github.com/jquery/jquery/commits/1.4/src/ajax.js

@Ben, I think it boils down to their switch to using 'proper' JSON parsing. "{"a":1,"b":undefined}" must not be valid JSON.

In order to avoid reading the entire spec (because I want to go running before lunch), I made this simple test to prove my hypothesis:

[Console]
var data = {a: 1, b: undefined};
JSON.stringify(data); //"{"a":1}"

Of course, only a subset of browsers support JSON.stringify. TBH, I don't see where jQuery stringifys (which it doesn't provide direct support for, because of these reasons http://bugs.jquery.com/ticket/5947).

I would like to see how IE6/7 work with this same type of request. Anyways, the $.ajax demo is available here: http://jsfiddle.net/xEym4/

You are right, I don't believe this is a bug and a very good thing to know. Thanks!


Feb 18, 2011 at 9:38 AM // reply »
10,743 Comments

@Drew,

I just hope that it is working the same way across browsers, given then same version of jQuery. I thought maybe it had to do with the iteration over the object; but, you can check for keys with undefined values and they do exist.


Feb 27, 2012 at 2:10 PM // reply »
347 Comments

@Ben,

I wanted to thank you so much for this! I was having a little problem with my jquery I had written, and I did a search on Google. Your blog popped up about the 5th or 6th answer down. Because they were above yours, I checked the others first before even realizing it was your blog. Your blog was the only one out of the list that helped me. (and that was actually my second search for this) It really helped a lot. Thanks so much!!! You are such a huge help to me when I have problems pop up with my coding, both big and small. This was a problem I had been spending quite a bit of time trying to solve. Your solution here helped me so much...and I am writing using php with jquery and not ColdFusion! Yet it still helped immensely. Thank you so much! Do you know if you happen to have a blog related to a loading gif for when jquery is doing work with the database so users understand that something is going on and happening behind the scenes and don't go crazy with your app? Just thought I'd ask. But anyway, regardless...thanks so much for all of the help I've already gotten from you.


Feb 27, 2012 at 2:12 PM // reply »
347 Comments

*of course, I meant do you know if you have a blog post for that...I wouldn't expect you to have an entire blog dedicated solely to that. Just wanted to clarify. :-D



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 16, 2012 at 8:18 PM
Best Of ColdFusion 10 Contest Entry - HTML Email Utility
Just found this, looks good! I'm trying to run it on local, it's the 64bit version and I'm experiencing horrible lag. On average the generate.cfm processes the content change in 60-90 seconds. I've ... read »
May 16, 2012 at 6:40 PM
Maintaining Sessions Across Multiple ColdFusion CFHttp Requests
I am trying to integrate this CFHTTPsession into an application that will log into zeekrewards.com to post ads and I am not having any luck. The code works perfectly for logging into other websites, ... read »
May 16, 2012 at 2:44 PM
Creating A Sometimes-Fixed-Position Element With jQuery
Thank you, very useful technique! Worked like a charm. ... read »
May 16, 2012 at 1:58 PM
Movies As A Religious Experience
Acting can, in a way, ruin the movie-goer's experience. I used to be able to get so caught up in movies and their plots, and totally engaged. But lately, I haven't been able to as much with a lot o ... read »
May 16, 2012 at 1:52 PM
The Science Of Optimal Post-Exercise Nutrition
children of this age eat very less vegetables so u can opt for salads they will like it also carrot ,cucumber,onion and as far as pulses are concerned u can boil them ,give him along with mashed rice ... read »
May 16, 2012 at 1:34 PM
Strange ColdFusion JRUN Stack Overflow Error
Hey, Recently I updated my jrun4 using the latest updater 7 and now i am having memory issues :(:(:( any help is appreciated ... read »
May 16, 2012 at 9:56 AM
ColdFusion 10 Beta, Apache Tomcat, And Symbolic Links On Mac OSX
Hi, Now that ColdFusion 10 is out I have stumbled over this as well and I cannot figure out the proper solution. We're running virtual hosts via Apache2; the ColdFusion-applications store their fil ... read »
May 15, 2012 at 6:03 PM
Movies As A Religious Experience
@Ben, I don't know whether you'd consider this a religious observation, but it seems to me, in a sense, movies multiply how many lives we get to have. Each movie is like a little extra life we get ... read »