Type Safety for your Backbone Models.
- Strict typing on model properties
- Disallow undeclared properties in constructor and set
- Deep JSON both ways (set internal models with a nested JSON and generate JSON from nested models)
fields
does not replace defaults, but runs in addition to it.
fields: {
propertyName: {
type: 'string',
value: 'defaultValue',
validate: function() {
//run validation check
},
transform: function() {
//return changed value
}
},
anotherPropertyName: {
type: 'number',
value: 3.1416, // default value
validate: function() {
// run validation check
},
transform: function() {
// return changed value
}
}
}
None of the fields
properties are required.
fields: {
propertyName: {}
}
- BackboneModel (reference)
- BackboneCollection (reference)
- SpecificClass (reference)
- 'string' || String ('foo')
- 'number' || Number (0, 1, 3.14159)
- 'integer' (-7, 1, 2, 42)
- 'array' || Array ([])
- 'object' || Object ({})
- 'boolean' || Boolean (true, false)
- 'regexp' || RegExp (/foo.*bar/g)
- 'date' || Date (date object)
All types accept null as their value.
- '_class' - Reserved for a non-Backbone class data type
- '_model' - Reserved for Backbone Model
- '_collection' - Reserved for Backbone Collection
Using any of the reserved data types will result in an error.
Any other data types besides those listed in the Supported Types section will generate an error.
.set() accepts either a BackboneModel of the correct type or an object literal that validates when creating an instance of that type. Any set completely overrides prior value.
.set() accepts either a BackboneCollection of the correct type reference or an array containing object literals or backbone models. Any set completely overrides prior value.
.set() accepts either a string or a Date object in JSON date format ('2012-06-14T22:42:42.229Z') or a Date.toString() format ('Thu Jun 14 2012 15:50:31 GMT-0700 (PDT)'). If it's a string, we convert it into a Date object.
.set() accepts either a string of a regexp or a RegExp object. If it is a regexp string, we convert it into a RegExp object.
set/constructor > model._validate():
- attr.tranform()
- attr.validate()
- attr._typeCheck()
If both validate
and _typeCheck
pass, continue with normal execution (actually set the attr value).
Accepts a function. Returns the converted value of the attr. Used to convert passed-in value into the data type appropriate for this attribute, such as converting a string "123" into a number 123. If the value cannot be converted, the function will return 'undefined'.
Accepts a function, which returns either nothing or an error string/object, just like Backbone's validate
method. If validate
returns an error, set
and save
will not continue, and the model attributes will not be modified. Failed validations trigger an "error" event.
This is an internal method to test validity of the attribute value after all other conversions and validations have been done. Do not overwrite.
Only properties that are declared in fields
or in the standard defaults
will be allowed for set and constructor. Any other values will trigger an "error" event.
This only happens if fields
is declared in the model.
Here are the possible scenarios for interaction between properties set in fields
and defaults
:
- If a property is defined in
defaults
but not infields
or iffields
entry for that property does not containvalue
, it will be automatically added to thefields
hash. - If a property is defined in
fields
, but not indefaults
, it will be automatically added to thedefaults
hash. - If a property is defined in both the
defaults
andfields
with avalue
parameter set and the value is different between the two, an "error" event will get triggered during construction.
Examples:
defaults: {
title: 'FooBar'
}
// is the same as
fields: {
title: {
value: 'FooBar'
}
}
// This will cause an "error" event to trigger during construction
// due to conflict in setting default value:
defaults: {
title: 'FooBar'
},
fields: {
title: {
value: 'BarBaz'
}
}
var ChildModel = Backbone.Model.extend({
fields: {
childProperty: {
type: 'string'
}
}
});
var Foo = Backbone.Model.extend({
fields: {
childModel: {
type: ChildModel
}
}
});
var foo = new Foo({
childModel: {
childProperty: 'value'
}
});
foo.toJSON({
noDefaults: true,
include: ['id', 'title']
});
If the noDefaults
parameter is set to true
, the output from toJSON
will exclude any attributes whose values are the same as the default values of that model.
A whitelist array of attributes to include in the JSON output.
NOTE: Will add support for nesting in the future:
foo.toJSON({
include: ['id', 'title', 'attrModel.id']
});
Add toJSON method to each attr that is of type regexp.
A useful pattern is to have the default value for a collection be an empty collection, that way when you do:
modelInstance.get('collectionName').each(function() { ... })
you won't have to check to see if the collection is set or not. Though you can still check its length.
Model methods that will be overwritten:
- constructor (?)
- get (?)
- set (?)
- _validate
- toJSON