I got started with Backbone.js validations yesterday. My initial approach was, at best, rudimentary. Fortunately, my co-author on the forthcoming Recipes with Backbone, Nick Gauthier, had some advice on how to improve.
So first up, I drop my basic validation handler in favor of one on the my view. Each appointment in my calendar application is controlled by a Backbone view, so this is where I add my error handling:
var Appointment = Backbone.View.extend({
template: _.template($('#calendar-appointment-template').html()),
initialize: function(options) {
// ...
options.model.bind('error', this.handleError, this);
},
handleError: function(model, error) {
if (error.status == 409) {
alert("This site does not understand CouchDB revisions.");
}
else if (typeof(error == 'Array')) {
alert(error.join("\\n"));
}
else {
alert("This site was made by an idiot.");
}
},
});The 409 HTTP status check is for errors that might originate from my CouchDB data store. As Nick points out, I should move this into Backbone.sync so that my view does not have to be aware of things like the data store's error messages. I will worry about that another day.For now, this addition of the check for errors of type
'Array', should account for the errors that I am setting in my model: var Models = (function() {
var Appointment = Backbone.Model.extend({
// ...
validate: function(attributes) {
var errors = [];
if (!(/\\S/.test(attributes.title)))
errors.push("Title cannot be blank.");
if (!/\\S/.test(attributes.description))
errors.push("Description cannot be blank.");
if (errors.length > 0)
return errors;
},
// ...
});And this does work. When I attempt to edit an existing appointment and remove the required description, I am greeted with:That is fine and dandy, but I get no error feedback at all when creating appointments. My add-appointment view is a singleton view, primarily because it is using a jQuery UI dialog to present the form:
Nick had suggested binding a view's event listener to the model's error handler, similar to what I am doing with the appointment view:
var Appointment = Backbone.View.extend({
template: _.template($('#calendar-appointment-template').html()),
initialize: function(options) {
// ...
options.model.bind('error', this.handleError, this);
},
// ...
});But I have to confess that I do not know how I would go about doing this with a singleton view. What I do know how to do in a singleton view is add an "error" callback to the create() method:var AppointmentAdd = new (Backbone.View.extend({
// ...
events: {
'click .ok': 'create'
},
create: function() {
var attributes = {
title: this.el.find('input.title').val(),
description: this.el.find('input.description').val(),
startDate: this.el.find('.startDate').html()
};
var options = {
success: function() { $('#add-dialog').dialog("close"); },
error: function(model, errors) {
$('.errors', '#add-dialog').html(errors.join("<br/>")).show();
}
};
appointment_collection.create(attributes, options);
}
}));Now, when I try to create an invalid appointment, I am greeted with:This gives me a chance to correct my mistake and save successful. Upon successful save, the dialog is hidden from view.
That kinda works. I will call it a night here and see what my co-author (or anyone else) has to say about my solution.
Day #153



No comments:
Post a Comment