I have a testcase where I want to send a request to the server every time a form field change
event occurs. The implementation below works as expected until I submit the form and check for any empty values(this is the only front-end validation carried out, the rest is done via ajax). If a field is empty I trigger a change
event so validation can be carried out on the server side.
In the example below I had to set async=>false
so each trigger would would as expected. I realize this is not ideal and there is a better way around this using deferred/promise patterns.
I am already using somewhat of the pattern .promise
and .then
however I think I need to use the .when
method but am unsure how to work it into my partially working example.
I am also a little unsure of the amount of request being sent to the server. Is it viable to send this many, i.e.: each time an event occurs?
Please ignore the block comments, I just use them for code separation.
(function($){
var Registration= {};
/**
*
* @type type
**/
Registration.fields = {};
/**
*
* @type type
**/
Registration.options = {
cache : false,
type : 'POST',
dataType : 'json',
url : SITE_URL + '/members/validateFieldOnChange',
context : undefined,
data : undefined,
async : false // TODO
};
/**
*
* @returns {undefined}
**/
Registration.init = function(){
//caching
this.Form = $('form#form-register');
this.fields = {
username : this.Form.find('#username'),
email : this.Form.find('#email'),
password : this.Form.find('#password'),
};
// register event handlers
this.Form.on('change', 'input', $.proxy(this.handleEvents, this));
this.Form.on('submit', $.proxy(this.handleEvents, this));
};
/**
*
* @param {type} event
* @returns {undefined}
**/
Registration.handleEvents = function(event){
var type, target
event.preventDefault();
type = event.type;
target = event.target;
if(type == 'change'){
return this.handleChangeEvent(event.target);
}
return this.handleSubmitEvent();
};
/**
*
* @param {type} target
* @returns {undefined}
**/
Registration.handleChangeEvent = function(target){
this.options.context = target;
this.options.data = { field : target.name, value : target.value}
return this.validate();
};
/**
*
* @returns {undefined}
**/
Registration.handleSubmitEvent = function(){
// Ugly testcase if values are empty
// TODO
if($('#username').val() == ''){
$('#username').trigger('change');
}
if($('#email').val() == ''){
$('#email').trigger('change');
}
if($('#password').val() == ''){
$('#password').trigger('change');
}
};
/**
*
* @returns {_L2.Registration@call;doAjax@call;then}
**/
Registration.validate = function(){
return this.doAjax().then(
$.proxy(this.handleResponse, this),
$.proxy(this.handleError, this)
);
};
/**
*
* @param {type} response
* @returns {undefined}
**/
Registration.handleResponse = function(response){
var field = $(this.options.context);
if(response.msg == 'success')
{
field.addClass('valid');
}
else
{
field.val('');
field.attr('placeholder', response.responseError);
field.addClass('invalid');
}
return;
};
/**
*
* @param {type} error
* @returns {undefined}
**/
Registration.handleError = function(error){
switch(error.code)
{
case 404:
return console.error('Not found');
break;
case 401:
return console.error('un-authorized access!');
break;
case 500:
return console.error('system error!');
break;
}
};
/**
*
* @returns {unresolved}
**/
Registration.doAjax = function(){
return $.ajax(this.options).promise();
}
Registration.init();
})(jQuery);
async
tofalse
. Is it because you need the three change events you generate to finish processing before the form submits? Is that the problem you're trying to solve? If so, I don't understand why you're manually validating each field with the server and then always sending the whole form to the server. Why not either stop the form submission if something doesn't validate or just validate the whole form when it is received on the server and return a response from the form submission? – jfriend00 Apr 2 at 23:00