Created
August 15, 2013 18:42
-
-
Save dylants/6243526 to your computer and use it in GitHub Desktop.
Backbone Validation setup (with Backbone 1.0, backbone.validation plugin, and bootstrap integration)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* MODEL | |
*/ | |
return Backbone.Model.extend({ | |
urlRoot: "/api/resource", | |
defaults: { | |
id: null, | |
name: null, | |
num: null, | |
amount: null | |
}, | |
validation: { | |
name: { | |
required: true, | |
msg: "Please enter a name" | |
}, | |
num: { | |
required: true, | |
pattern: "digits", | |
msg: "Please enter a number for num" | |
}, | |
amount: { | |
required: true, | |
pattern: "number", | |
msg: "Please enter an amount" | |
} | |
} | |
}); | |
/* | |
* VIEW | |
*/ | |
return Backbone.View.extend({ | |
el: "main", | |
template: _.template(html), | |
events: { | |
"click #submit": "submitForm", | |
"blur input, textarea": "updateModel" | |
}, | |
initialize: function() { | |
this.model.on("sync", this.render, this); | |
if (this.model.get("id")) { | |
this.model.fetch(); | |
} | |
}, | |
close: function() { | |
// release all event listeners | |
this.model.stopListening(); | |
this.stopListening(); | |
this.$el.off("click"); | |
this.$el.off("blur"); | |
}, | |
render: function() { | |
$(this.el).html(this.template(this.model.toJSON())); | |
// binds the backbone.validation plugin to this view's actions | |
Backbone.Validation.bind(this); | |
return this; | |
}, | |
updateModel: function(el) { | |
var targetEl, changedAttributes; | |
// every time the user blurs an input, we'll validate that input | |
targetEl = $(el.target); | |
this.model.set(targetEl.attr("name"), targetEl.val()); | |
// backbone has changed since the release of backbone.validation plugin | |
// so we're required to manually call validate on the model after a set | |
// and, we must pass in the changed attributes or else it will validate | |
// everything in the model, including the default values | |
changedAttributes = this.model.changedAttributes(); | |
if (changedAttributes) { | |
this.model.validate(changedAttributes); | |
} | |
}, | |
formSubmit: function(ev) { | |
var values; | |
ev.preventDefault(); | |
// hide the negative message (if it exists) | |
this.$(".alert").hide(); | |
// serialize the form, setting the values in the model, then validate | |
values = this.$("form").serializeObject(); | |
if (!this.model.set(values, {validate: true})) { | |
// if validation failed, show the error message | |
// (individual fields are handled by the bootstrap integration below) | |
this.$(".alert-danger").fadeIn(); | |
} | |
// save model, etc... | |
}, | |
}); | |
/* | |
* BACKBONE VALIDATION PLUGIN | |
*/ | |
// Source can be downloaded from here: | |
// http://thedersen.com/projects/backbone-validation/#download-and-source-code | |
/* | |
* BOOTSTRAP INTEGRATION -- HTML TEMPLATE | |
*/ | |
// If messages are to be displayed on the individual fields, every input in the template's HTML needs to include | |
// an error style. This can be nothing (for no message displayed, but red highlight on the input), tooltip, or | |
// inline. Like so: | |
// | |
<form> | |
<div class="alert alert-danger" style="display:none"> | |
Please enter correct values for the fields below | |
</div> | |
<fieldset> | |
<legend>Form Details</legend> | |
<div class="form-group"> | |
<label class="control-label">Name: | |
<input type="text" class="form-control" name="name" id="name" value="<%- name %>" data-error-style="tooltip"/> | |
</label> | |
</div> | |
.... | |
/* | |
* BOOTSTRAP INTEGRATION -- JAVASCRIPT | |
*/ | |
_.extend(Backbone.Validation.callbacks, { | |
valid: function (view, attr, selector) { | |
var control, group; | |
control = view.$('[' + selector + '=' + attr + ']'); | |
group = control.parents(".control-label"); | |
group.removeClass("has-error"); | |
if (control.data("error-style") === "tooltip") { | |
control.tooltip("hide"); | |
} else if (control.data("error-style") === "inline") { | |
group.find(".help-inline").remove(); | |
} else { | |
group.find(".help-block").remove(); | |
} | |
}, | |
invalid: function (view, attr, error, selector) { | |
var control, gropu, position, target; | |
control = view.$('[' + selector + '=' + attr + ']'); | |
group = control.parents(".control-label"); | |
group.addClass("has-error"); | |
if (control.data("error-style") === "tooltip") { | |
position = control.data("tooltip-position") || "right"; | |
control.tooltip({ | |
placement: position, | |
trigger: "manual", | |
title: error | |
}); | |
control.tooltip("show"); | |
} else if (control.data("error-style") === "inline") { | |
if (group.find(".help-inline").length === 0) { | |
group.find(".controls").append("<span class=\"help-inline\"></span>"); | |
} | |
target = group.find(".help-inline"); | |
target.text(error); | |
} else { | |
if (group.find(".help-block").length === 0) { | |
group.find(".controls").append("<p class=\"help-block\"></p>"); | |
} | |
target = group.find(".help-block"); | |
target.text(error); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment