Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
backbone-validation
Advanced tools
![Version](https://img.shields.io/npm/v/backbone-validation.svg?style=flat) ![Downlodas](https://img.shields.io/npm/dm/backbone-validation.svg?style=flat) ![Dependencies](https://david-dm.org/thedersen/backbone.validation.svg?style=flat) ![license](http:/
A validation plugin for Backbone.js that validates both your model as well as form input.
Good client side validation is an important part of giving your users a great experience when they visit your site. Backbone provides a validate method, but it is left undefined and it is up to you to override it with your custom validation logic. Too many times I have seen validation implemented as lots of nested ifs and elses. This quickly becomes a big mess. One other thing is that with libraries like Backbone, you hold your state in a Model, and don't tie it to the DOM. Still, when validating your models you probably want to inform your users about errors etc., which means modifying the DOM.
Backbone.Validation tries to solve both these problems. It gives you a simple, extensible way of declaring validation rules on your model, and overrides Backbone's validate method behind the scene. And, it gives you a nice hook where you can implement your own way of showing the error messages to your user.
If you are using node.js on the server you can also reuse your models and validation on the server side. How cool is that?
Backbone.Validation is a bit opinionated, meaning that you have to follow some conventions in order for it to work properly.
You can download the raw source from GitHub, see the annotated source or use the links below for the latest stable version.
npm install backbone-validation
bower install backbone-validation
It's easy to get up and running. You only need to have Backbone (including underscore.js) in your page before including the Backbone.Validation plugin. If you are using the default implementation of the callbacks, you also need to include jQuery.
The plugin is tested with, and should work with the following versions of
To configure your validation rules, simply add a validation property with a property for each attribute you want to validate on your model. The validation rules can either be an object with one of the built-in validators or a combination of two or more of them, or a function where you implement your own custom validation logic.
Validating complex objects is also supported. To configure validation rules for objects, use dot notation in the name of the attribute, e.g 'address.street'
.
var SomeModel = Backbone.Model.extend({
validation: {
name: {
required: true
},
'address.street': {
required: true
},
'address.zip': {
length: 4
},
age: {
range: [1, 80]
},
email: {
pattern: 'email'
},
someAttribute: function(value) {
if(value !== 'somevalue') {
return 'Error message';
}
}
}
});
// validation attribute can also be defined as a function returning a hash
var SomeModel = Backbone.Model.extend({
validation: function() {
return {
name: {
required: true
}
}
}
});
See the built-in validators section for a list of the validators and patterns that you can use.
Backbone.Validation comes with a set of default error messages. If you don't like to use those, you can either override them, or you can specify error messages where you declare validation rules on the model.
You can specify an error message per attribute by adding a msg
property like this:
MyModel = Backbone.Model.extend({
validation: {
email: {
required: true,
pattern: 'email',
msg: 'Please enter a valid email'
}
}
});
Or, you can specify an error message per validator, by adding an array of validators like this:
MyModel = Backbone.Model.extend({
validation: {
email: [{
required: true,
msg: 'Please enter an email address'
},{
pattern: 'email',
msg: 'Please enter a valid email'
}]
}
});
The msg
property can also be a function returning a string.
The philosophy behind this way of using the plugin, is that you should be able to reuse your validation rules both to validate your model and to validate form input, as well as providing a simple way of notifying users about errors when they are populating forms.
Note that Backbone.Validation does not provide any automatic/two-way binding between your model and the view, that's up you to implement (you can for instance use Backbone.stickit).
Before you can start using form validation, you need to bind your view.
The validation binding code is executed with a call to Backbone.Validation.bind(view)
. There are several places that it can be called from, depending on your circumstances, but it must be called after your model or collection has been initialized.
// Binding when rendering
var SomeView = Backbone.View.extend({
render: function(){
Backbone.Validation.bind(this);
}
});
// Binding when initializing
var SomeView = Backbone.View.extend({
initialize: function(){
Backbone.Validation.bind(this);
}
});
// Binding from outside a view
var SomeView = Backbone.View.extend({
});
var someView = new SomeView({model: new SomeModel()});
Backbone.Validation.bind(someView);
// Binding to a view with an optional model
var myModel = new Backbone.Model();
var SomeView = Backbone.View.extend({
initialize: function(){
Backbone.Validation.bind(this, {
model: myModel
});
}
});
// Binding to a view with an optional collection
var myCollection = new Backbone.Collection();
var SomeView = Backbone.View.extend({
initialize: function(){
Backbone.Validation.bind(this, {
collection: myCollection
});
}
});
For this to work, your view must have an instance property named model that holds your model before you perform the binding, or you can pass an optional model in the options as shown in the example above.
When binding to a view with a model, Backbone's validate method on the model is overridden to perform the validation. In addition, the model's isValid method is also overridden to provide some extra functionality.
It is possible to bind several views to the same model. This is specially useful in UI structures where forms are made with components that share models.
When the model is validated all associated views with attributes from that model will validate its related elements.
It is also possible to unbind each view separately without affecting other bindings.
For this to work, your view must have an instance property named collection that holds your collection before you perform the binding, or you can pass an optional collection in the options as shown in the example above.
When binding to a view with a collection, all models in the collection are bound as described previously. When you are adding or removing models from your collection, they are bound/unbound accordingly.
Note that if you add/remove models with the silent flag, they will not be bound/unbound since there is no way of knowing the the collection was modified.
If you want to remove the validation binding, this is done with a call to Backbone.Validation.unbind(view)
. This removes the validation binding on the model, or all models if you view contains a collection, as well as removing all events hooked up on the collection.
Note that if you are binding to an optional model or collection, you must also specify this when unbinding: Backbone.Validation.unbind(view, {model: boundModel})
.
The philosophy behind this way of using the plugin, is to give you an easy way to implement validation across all your models without the need to bind to a view. Of course, if you use this option the callbacks to update the view is not executed, since there is no way of knowing what view a model belongs to.
To add validation to your models, mix in the validation on the Model's prototype.
_.extend(Backbone.Model.prototype, Backbone.Validation.mixin);
If you are using node.js on your server, you can also reuse your models and validation on the server. For this to work you must share your models between the server and the client.
var backbone = require('backbone'),
_ = require('underscore'),
validation = require('backbone-validation');
_.extend(backbone.Model.prototype, validation.mixin);
This is called by Backbone when it needs to perform validation. You can also call it manually without any parameters to validate the entire model.
Check to see if an attribute, an array of attributes or the entire model is valid.
isValid
returns undefined
when no validation has occurred and the model has validation (except with Backbone v0.9.9 where validation is called from the constructor), otherwise, true
or false
.
If you don't pass an argument, the properties defined by the attributes
bind option will be validated. If no attributes
option is used there will be no validation.
var isValid = model.isValid();
If you pass true
as an argument, this will force a validation before the result is returned:
var isValid = model.isValid(true);
If you pass the name of an attribute or an array of names, you can check whether or not the attributes are valid:
// Check if name is valid
var isValid = model.isValid('name');
// Check if name and age are valid
var isValid = model.isValid(['name', 'age']);
Sometimes it can be useful to check (for instance on each key press) if the input is valid - without changing the model - to perform some sort of live validation. You can execute the set of validators for an attribute, or a hash of attributes, by calling the preValidate
method and pass it the name of the attribute and the value to validate, or a hash of attributes.
If the value is not valid, the error message is returned (truthy), otherwise it returns a falsy value.
// Validate one attribute
// The `errorsMessage` returned is a string
var errorMessage = model.preValidate('attributeName', 'Value');
// Validate a hash of attributes
// The errors object returned is a key/value pair of attribute name/error, e.g
// {
// name: 'Name is required',
// email: 'Email must be a valid email'
// }
var errors = model.preValidate({name: 'value', email: 'foo@example.com'});
The Backbone.Validation.callbacks
contains two methods: valid
and invalid
. These are called after validation of an attribute is performed when using form validation.
The default implementation of invalid
tries to look up an element within the view with an name attribute equal to the name of the attribute that is validated. If it finds one, an invalid
class is added to the element as well as a data-error
attribute with the error message. The valid
method removes these if they exists.
The implementation is a bit naïve, so I recommend that you override it with your own implementation
globally:
_.extend(Backbone.Validation.callbacks, {
valid: function(view, attr, selector) {
// do something
},
invalid: function(view, attr, error, selector) {
// do something
}
});
or, per view when binding:
var SomeView = Backbone.View.extend({
render: function(){
Backbone.Validation.bind(this, {
valid: function(view, attr) {
// do something
},
invalid: function(view, attr, error) {
// do something
}
});
}
});
Default: name
This configures what selector that will be used to look up a form element in the view. By default it uses name, but if you need to look up elements by class name or id instead, there are two ways to configure this.
You can configure it globally by calling:
Backbone.Validation.configure({
selector: 'class'
});
Or, you can configure it per view when binding:
Backbone.Validation.bind(this.view, {
selector: 'class'
});
If you have set the global selector to class, you can of course set the selector to name or id on specific views.
Default: false
Sometimes it can be useful to update the model with invalid values. Especially when using automatic modelbinding.
You can turn this on globally by calling:
Backbone.Validation.configure({
forceUpdate: true
});
Or, you can turn it on per view when binding:
Backbone.Validation.bind(this.view, {
forceUpdate: true
});
Or, you can turn it on for one set operation only (Backbone.VERSION >= 0.9.1 only):
model.set({attr: 'invalidValue'}, {
forceUpdate: true
});
Note that when switching this on, Backbone's error event is no longer triggered.
Default: sentenceCase
Label formatters determines how an attribute name is transformed before it is displayed in an error message.
There are three options available:
attributeName
or attribute_name
to Attribute namevar Model = Backbone.Model.extend({
validation: {
someAttribute: {
required: true
}
},
labels: {
someAttribute: 'Custom label'
}
});
To configure which one to use, set the labelFormatter options in configure:
Backbone.Validation.configure({
labelFormatter: 'label'
});
The attributes
option passed in Backbone.Validation.bind determines what model attributes must be validated. It can be an array, a function returning an array or an string that points to an registered attribute loader. By default, the 'inputNames' attribute loader is provided. It returns the name attribute of input elements in the view.
Per view when binding:
var SomeView = Backbone.View.extend({
render: function(){
Backbone.Validation.bind(this, {
attributes: function(view) {
return ['name', 'age']; // only name and age will be validated
}
}
});
}
});
Set default globally:
Backbone.Validation.configure({
attributes: 'inputNames' // returns the name attributes of bound view input elements
});
Register an attribute loader:
_.extend(Backbone.Validation.attributeLoaders, {
myLoader: function(view) {
// return an array with the attributes to be validated
}
});
After validation is performed, the model will trigger some events with the result of the validation.
Note that the events reflects the state of the model, not only the current operation. So, if for some reason your model is in an invalid state and you set a value that is valid, validated:invalid
will still be triggered, not validated:valid
.
The errors
object passed with the invalid events is a key/value pair of attribute name/error.
{
name: 'Name is required',
email: 'Email must be a valid email'
}
The validated
event is triggered after validation is performed, either it was successful or not. isValid
is true
or false
depending on the result of the validation.
model.bind('validated', function(isValid, model, errors) {
// do something
});
The validated:valid
event is triggered after a successful validation is performed.
model.bind('validated:valid', function(model) {
// do something
});
The validated:invalid
event is triggered after an unsuccessful validation is performed.
model.bind('validated:invalid', function(model, errors) {
// do something
});
Lets you implement a custom function used for validation.
var SomeModel = Backbone.Model.extend({
validation: {
name: function(value, attr, computedState) {
if(value !== 'something') {
return 'Name is invalid';
}
}
}
});
var SomeModel = Backbone.Model.extend({
validation: {
name: {
fn: function(value, attr, computedState) {
if(value !== 'something') {
return 'Name is invalid';
}
}
}
}
});
Lets you implement a custom function used for validation.
var SomeModel = Backbone.Model.extend({
validation: {
name: 'validateName'
},
validateName: function(value, attr, computedState) {
if(value !== 'something') {
return 'Name is invalid';
}
}
});
var SomeModel = Backbone.Model.extend({
validation: {
name: {
fn: 'validateName'
}
},
validateName: function(value, attr, computedState) {
if(value !== 'something') {
return 'Name is invalid';
}
}
});
Validates if the attribute is required or not. This can be specified as either a boolean value or a function that returns a boolean value.
var SomeModel = Backbone.Model.extend({
validation: {
name: {
required: true | false
}
}
});
var SomeModel = Backbone.Model.extend({
validation: {
name: {
required: function(value, attr, computedState) {
return true | false;
}
}
}
});
Validates that something has to be accepted, e.g. terms of use. true
or 'true' are valid.
var SomeModel = Backbone.Model.extend({
validation: {
termsOfUse: {
acceptance: true
}
}
});
Validates that the value has to be a number and equal to or greater than the min value specified.
var SomeModel = Backbone.Model.extend({
validation: {
age: {
min: 1
}
}
});
Validates that the value has to be a number and equal to or less than the max value specified.
var SomeModel = Backbone.Model.extend({
validation: {
age: {
max: 100
}
}
});
Validates that the value has to be a number and equal to or between the two numbers specified.
var SomeModel = Backbone.Model.extend({
validation: {
age: {
range: [1, 10]
}
}
});
Validates that the value has to be a string with length equal to the length value specified.
var SomeModel = Backbone.Model.extend({
validation: {
postalCode: {
length: 4
}
}
});
Validates that the value has to be a string with length equal to or greater than the min length value specified.
var SomeModel = Backbone.Model.extend({
validation: {
password: {
minLength: 8
}
}
});
Validates that the value has to be a string with length equal to or less than the max length value specified.
var SomeModel = Backbone.Model.extend({
validation: {
password: {
maxLength: 100
}
}
});
Validates that the value has to be a string and equal to or between the two numbers specified.
var SomeModel = Backbone.Model.extend({
validation: {
password: {
rangeLength: [6, 100]
}
}
});
Validates that the value has to be equal to one of the elements in the specified array. Case sensitive matching.
var SomeModel = Backbone.Model.extend({
validation: {
country: {
oneOf: ['Norway', 'Sweeden']
}
}
});
Validates that the value has to be equal to the value of the attribute with the name specified.
var SomeModel = Backbone.Model.extend({
validation: {
password: {
required: true
},
passwordRepeat: {
equalTo: 'password'
}
}
});
Validates that the value has to match the pattern specified. Can be a regular expression or the name of one of the built in patterns.
var SomeModel = Backbone.Model.extend({
validation: {
email: {
pattern: 'email'
}
}
});
The built-in patterns are:
Specify any regular expression you like:
var SomeModel = Backbone.Model.extend({
validation: {
email: {
pattern: /^sample/
}
}
});
If you have custom validation logic that are used several places in your code, you can extend the validators with your own. And if you don't like the default implementation of one of the built-ins, you can override it.
_.extend(Backbone.Validation.validators, {
myValidator: function(value, attr, customValue, model) {
if(value !== customValue){
return 'error';
}
},
required: function(value, attr, customValue, model) {
if(!value){
return 'My version of the required validator';
}
},
});
var Model = Backbone.Model.extend({
validation: {
age: {
myValidator: 1 // uses your custom validator
}
}
});
The validator should return an error message when the value is invalid, and nothing (undefined
) if the value is valid. If the validator returns false
, this will result in that all other validators specified for the attribute is bypassed, and the attribute is considered valid.
If you have custom patterns that are used several places in your code, you can extend the patterns with your own. And if you don't like the default implementation of one of the built-ins, you can override it.
Remember to also provide a default error message for it.
_.extend(Backbone.Validation.patterns, {
myPattern: /my-pattern/,
email: /my-much-better-email-regex/
});
_.extend(Backbone.Validation.messages, {
myPattern: 'This is an error message'
});
var Model = Backbone.Model.extend({
validation: {
name: {
pattern: 'myPattern'
}
}
});
If you don't like the default error messages you can easilly customize them by override the default ones globally:
_.extend(Backbone.Validation.messages, {
required: 'This field is required',
min: '{0} should be at least {1} characters'
});
The message can contain placeholders for arguments that will be replaced:
{0}
will be replaced with the formatted name of the attribute being validated{1}
will be replaced with the allowed value configured in the validation (or the first one in a range validator){2}
will be replaced with the second value in a range validatorIf you have other cool examples, feel free to fork the fiddle, add a link here, and send me a pull request.
If you are using Backbone v0.9.1 or later, all attributes in a model will be validated. However, if for instance name
never has been set (either explicitly or with a default value) that attribute will not be validated before it gets set.
This is very useful when validating forms as they are populated, since you don't want to alert the user about errors in input not yet entered.
If you need to validate entire model (both attributes that has been set or not) you can call validate()
or isValid(true)
on the model.
Yes you can!
var Model = Backbone.Model.extend({
validation: {
name: function(val, attr, computed) {
return Backbone.Validation.validators.length(val, attr, 4, this);
}
}
});
Yes you can!
_.extend(Backbone.Validation.validators, {
custom: function(value, attr, customValue, model) {
return this.length(value, attr, 4, model) || this.custom2(value, attr, customValue, model);
},
custom2: function(value, attr, customValue, model) {
if (value !== customValue) {
return 'error';
}
}
});
By default, if you configure a validator for an attribute, it is considered required. However, if you want to allow empty values and still validate when something is entered, add required: false in addition to other validators.
validation: {
value: {
min: 1,
required: false
}
}
Yes, well, sort of. You can have conditional validation by specifying the required validator as a function.
validation: {
attribute: {
required: function(val, attr, computed) {
return computed.someOtherAttribute === 'foo';
},
length: 10
}
}
In the example above, attribute
is required and must have 10 characters only if someOtherAttribute
has the value of foo. However, when attribute
has any value it must be 10 characters, regardless of the value of someOtherAttribute
.
The default implementation of the callbacks are a bit naïve, since it is very difficult to make a general implementation that suits everybody.
My recommendation is to override the callbacks and implement your own strategy for displaying the error messages.
Please refer to this section for more details.
driehle put together a gist in Coffee Script that helps rendering the error messages for Twitter Bootstrap:
https://gist.github.com/2909552
Basic behaviour:
<p class="help-block">
(which has red text because of the error class)isValid
and call valid
/invalid
callbacks when passing array or name to isValid
.flatten
in validate
methodattributes
bind option allows to configure the attributes that will be validatedflatten()
method causing Maximum call stack size exceeded
errors. Fixes #260 #180 #210 #224 #233i
=> is
. Fixes #183preValidate
now accepts a hash of attributes in addition to a key/valuemsg
attribute can be defined as both a function or a stringvalidation
attribute can be defined as both a function or a hashformat(...)
and formatLabel(...)
are made available for custom validators on this
(Thanks to rafanoronha)labels
attribute is present on the modelcollectionAdd
function (Fixes #28, thanks to morgoth)toJSON()
validates correctly (Fixes #31, thanks to jasonzhao6)preValidate(attr, value)
method on validated models that can be used to preview if a value is valid or noterror
argument passed to the error event raised by Backbone is always an arrayisValid
to verify if the attribute(s) are validBackbone.Model.prototype
Backbone.Validation.validators
objectunbind
on a view without model no longer throws (Fixes #17)forceUpdate
can be specified when settings attributes (Backbone.VERSION >= 0.9.1 only)isValid
returns undefined
when no validatation has occured and the model has validationtrue
to isValid
forces an validationsetDefaultSelector
is removed, and you need to call configure({selector: 'class'})
insteadtrue
or false
as argumenterror
argument passed to the error event raised by Backbone contains an array of errors when validating multiple attributed in one go, otherwise a stringmodel.get('isValid')
) is replaced with a method model.isValid()
model.validate()
without any parameters. (Note: Backbone.Validation.bind(..)
must still be called)true
or false
In lieu of a formal styleguide, use two spaces for tabs and take care to maintain the existing coding style.
For a pull request to be accepted it must contain:
Make sure that all tests passes before submitting your pull request.
npm install -g grunt-cli
npm install
grunt
Backbone.Validation is inspired by Backbone.ModelBinding, and another implementation with a slightly different approach than mine at Backbone.Validations.
FAQs
![Version](https://img.shields.io/npm/v/backbone-validation.svg?style=flat) ![Downlodas](https://img.shields.io/npm/dm/backbone-validation.svg?style=flat) ![Dependencies](https://david-dm.org/thedersen/backbone.validation.svg?style=flat) ![license](http:/
The npm package backbone-validation receives a total of 6,747 weekly downloads. As such, backbone-validation popularity was classified as popular.
We found that backbone-validation demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.