I have spent waaay too much time trying to work out issues of mixing client side validation with Ajax validation.
Form has 5 text input fields.
Field number 1 needs server side validation so I use an ajax call -works great.
2 of the remaing 4 just need some client side validation.
Each onblur event validates and/or saves the field to a session object on the server.
If input fails validation, a list item is added to an error ul.
If there is an error, the submit button is disabled so they cannot submit the form until all errors are fixed.
If all errors are fixed. The save button is enabled, and an ajax call persists the session object. No data is resent to the server.
This is pretty much working except for when the user enters an invalid entry for field one, but instead of tabbing out, they click the submit button. In firefox it works as I would expect. The onblur fires first, and registers and error, which prevents the save function from persisting the form. But on IE, it looks like the onblur fires, but the onclick (from the save button) fires too.
I realize that this is tough to diagnos, but I am looking for: a). Should I do an Sajax call (a synchronous call for the validation). I think this would solve the valiation issue. b). Am I crazy and need to scrap this model and start over? c). Any good references that shows an example of combining both client side and Ajaxian validation. Not talking about "degrades nicely", which to me means do it all on the server or all on the client. I want to leverage the best of both worlds.
The problem you are facing is that you are relying on the onblur validation and not running a validation check on the submit button. There are multiple ways of doing the check. You can have flags set for each element and make sure it is validated, you can send out one big request/check on the submit button click.
I would perfer a flag method myself that would be able to detect if there are any active requests to the server. If there are, wait to they arew completed before proceeding.
My 2 cents. Eric
Joined: Apr 06, 2004
Congrats on the Ajax book. I am reading the e-version now and am finding some good gems.
I had orginally implemented a "validate on save" model go go along with the onblur validation. My problem with that model is the async nature of ajax request.
Basically an onSave function iterates through my form and looks for elements that had a title property of "validate".
I then run each element through a validation routine that performed custom validation based in the input's ID. They will return an isValid bool.
The second input elements needs an ajax validation.
Since the Ajax call is Async, control is returned to the doSave routine before the Ajax response is fielded.
I have a code snippet of the validation routine below. Pretty primitive, but should work. Is there a way I can have the save routine test to see if there is an XMLHttpRequest pending? I am using your ContentLoader object to create the request.
Another way I thought about doing this is to have doSave perform a single Ajax call that handles all server side validation for all inputs. I would then use the callback method to validate the rest of the inputs, and do the final save. I am uneasy about this, and feel it might lead to some memory leaks.
Now without this array holding the window, there is no way to know the number of windows opened by the user, unless we were to have an infinite number of global variables defined that we checked. Now with this we can loop through the array to check on the status of the objects that it contains. With the pop up example we check to see if the window is open, if it is than close it. Now these objects in the held within the array can be windows, custom objects, or even the Ajax Request.
So we can set the content loader into an array. When the form is submitted we can check the array to see if there are any processes that are still being run. If there are we can do one of two things:
1) Use a setTimeout to keep calling the function X milliseconds to wait until the process is finished to see if we can continue with the submission.
2)Set a flag which your Ajax functionality would check for after the validation is taken place. If the flag is true, then it knows to submit the form.
Or A simplier solution Eliminate the problem with the submit button. Disable it while the Ajax process is doing the validation. When the request is finished re-enable the button so it can be submitted.
You asked about how to get notification of whether a ContentLoader is still busy fetching something before you allow the form to be submitted. If you take a reference to the ContentLoader when you create it, i.e.
var myCL=new ContentLoader(myURL,myHandler,...)
then you'll be able to query myCL.req.readyState at any time. However, the easier way to do it is to get the ContentLoader to notify you when it's done, in the onload and onerror methods.
If you have several ContentLoaders firing from your form at once, you could increment and decrement a counter, so that you know when they're all done, like this (excuse all the big holes in the code, 'leave as an exercise to the reader' and all that!):
I'm assuming here that the validation will block the user from submitting via the submit button, which you have somehow got a reference to. I'm being bad here and using global variables, in production, I'd probably try to wrap this up in a Validator object of some sort.
Hope that's clear enough, if not, shout, and the Barman will come and get me again :-) (Hi, Eric)
Architecturally, there's a lot to be said for bundling all the HTTP calls in one go, or at least allowing for that possibility: - IE will launch a max of two http requests at once anyway (can be overridden in the registry, but it will be this way for most users) - the latency of a request is a much bigger overhead than the bandwidth consumed. Very 'chatty' http traffic will tend to scale poorly.
However, I recognise that your form validation needs to be pretty snappy in order to add any real value, so you'll have to make a decision one way or the other, probably based on a bit of profiling and tuning.
(By the way, I don't see a greater danger of memory leaks from a single http request than if using lots of little requests, but I may be missing something.)
Finally, as a general note of caution, if the validation matters, make sure you do sanity checks on the server too, otherwise a crafted http request could bypass the ajax layer altogether and inject invalid data into your system. I'm sure you're already aware of that.
---<br />Author of...<br />'Ajax in Action' <a href="http://manning.com/crane" target="_blank" rel="nofollow">http://manning.com/crane</a><br />'Prototype & Scriptaculous in Action'<br /><a href="http://manning.com/crane3" target="_blank" rel="nofollow">http://manning.com/crane3</a><br />'Ajax in Practice'<br /><a href="http://manning.com/crane2" target="_blank" rel="nofollow">http://manning.com/crane2</a>
Joined: Apr 06, 2004
Thank you both for your great responses!
I took Eric's idea and ran with it. After much pain of getting the timeouts to work properly (arrrgh!), I have a working model. There are definitely some holes that I need to plug, but it appears to be working (need test it under some load for sure).
David's solution handles the error case far better, and looks cleaner than mine, so I think I will tinker with it in the near future. Also thank you for the good tips on validation schemes.
I still gotta lot to learn about this stuff (I'd better get reading).