Skip to content

Instantly share code, notes, and snippets.

@dylants
Created August 15, 2013 18:42
Show Gist options
  • Save dylants/6243526 to your computer and use it in GitHub Desktop.
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)
/*
* 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