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