My thoughts currently are:
1) Screw the ajax, force a full page refresh each time
2) Render and pass the whole form back inside the response
3) Send back a validation error listing and parse it out in the client
#2 seems easiest, but I feel strange about it for some reason.
Anyone else tackle this before?
Interesting question, which anyone who ajaxifies a form has to answer. Umpirsky gave you a good solution. My two cents is: I have been using #3: sending back a JSON data structure that (maybe) contains a validationErrors object for the client to iterate through and display the errors. I also made a jQuery plugin for the sake of DRY. It's really primitive so I am a little embarrassed to show it, but... it's appended.
I too am using the ajaxContext/ target action json context, so on the controller side, simply
if ($form->isValid($this->getRequest()->getPost())) {
// process
} else {
$this->view->assign(array('validationErrors' => $form->getMessages()));
}
//////////////////////////// (crude) jQuery plugin
(function($) {
$.fn.ajaxFormPost = function(options) {
var form = $(this)[0];
// we have to be a FORM element
if (! 'FORM' == form.nodeName.toUpperCase()) {
alert("Error: $(this)[0] has to be a FORM element.");
return this;
}
var data = $(form).serialize()+'&format=json';
var submitButton = $(form).find("input[type=submit]");
var submitButtonText = submitButton.val();
var xhr = $.ajax(
{
type : 'POST',
url : $(form).attr('action'),
data : data,
dataType : 'json',
beforeSend : function(xhr) {
// clear any validation errors
$(".validationError").text('');
submitButton.val("Processing...");
},
success : function (data, textStatus) {
if (typeof(data.errorMessage) == 'string') {
if (typeof options.onError == 'function') {
return onError(data);
} else {
if ($('#errorMessage').length) {
return $('#errorMessage').text(data.errorMessage);
} else {
return $(form).prepend(
$("<div>")
.attr({
'class' : 'validationError',
id : 'errorMessage'
})
.css({
backgroundColor : 'yellow',
width:'50%',
padding:'.5em',
fontSize : '110%'
})
.text(data.errorMessage)
);
}
}
}
if (data.validationErrors) {
$.each(data.validationErrors, function(k,v){
var field = k; var errors = v;
$.each(errors,function(k,message) {
// if the error div does not exist, create it
if (! $('#error_'+field).length ) {
$('#'+field).before(
$('<div/>').attr({
id : "error_"+field ,
className:'validationError'
}).text(message)
);
} else {
$('#error_'+field).text(message);
}
return false; // once through is enough (max 1 error per form field)
});
});
} else {
if (typeof options.afterSuccess == 'function') {
options.afterSuccess(data);
}
}
},
// TO DO set this up as a global ajax thing? or as optional callback?
error : function(xhr,textStatus) {
alert('Sorry, a "'+ textStatus +'" error prevented us from completing your request. We have logged the event and will address it in due course.'+"\n\nIn the meantime you are encouraged to report this problem to the site administrator, describing what you were trying to do when this happened.");
},
complete : function(xhr,textStatus) {
submitButton.val(submitButtonText);
}
}
);
return this;
}
})(jQuery);
--
Support real health care reform:
http://phimg.org/
--
David Mintz
http://davidmintz.org/
没有评论:
发表评论