Backbone Events
Backbone events are a powerful way to write responsive user interfaces with fewer lines of codes. This article attempts to give a detailed breakdown of the events and the parameters available for the callback functions.
The results in this article are applicable for version 1.2.3 of Backbone.js
The test is performed by instantiating instances of
ExperimentModel
extended from
Backbone.Model
and ExperimentCollection
extended from Backbone.Collection
.
The model is first added to the collection to test "add" on the collection and then a properrty is set on the model.
var expModelA = new ExperimentModel({ id: 'a' });
var expCollA = new ExperimentCollection();
Add
expCollA.on('add', function (model, collection, obj) {
...
});
expModelA.on('add', function (model, collection, obj) {
...
});
expCollA.add(expModelA);
In both of the callback functions 3 parameters are passed:
-
model
-
- The model being added to the collection.
-
collection
-
The collection after the model is added.
-
operation object
-
A map containing the following keys (and values):
merge (false)
add (true)
remove (false)
Event | Model | Collection |
---|---|---|
add Event is triggered on the model and collection (in this sequence) when the model is added to the collection. |
Remove
expModelA.on('remove', function (model, collection, obj) {
...
});
expCollA.on('remove', function (model, collection, obj) {
...
});
expCollA.remove(expModelA);
In both of the callback functions 3 parameters are passed:
-
model
-
- The model being added to the collection.
-
collection
-
The collection after the model is added.
-
operation object
-
A map containing the following key (and value):
index
(the position in the collection of the model that was removed).
Event | Model | Collection |
---|---|---|
remove Event is triggered on the model and collection (in this sequence) when the model is removed from the collection. |
Update
expCollA.on('update', function (collection, obj) {
...
});
expCollA.add(expModelA);
expCollA.remove(expModelA);
The update
event is only called on the collection when a model is
added to or removed from the collection. Its callback function receives two
parameters:
-
collection
-
The collection after the model is added.
-
operation object
-
A map that contains different keys and values depending on the type of operation (add or remove). See Add and Remove for details.
Event | Model | Collection |
---|---|---|
update Event is triggered on the collection after
|
Sort
expCollA.on('sort', function (collection, obj) {
...
});
This event can be triggered when a model is added to/removed from the
collection. It can also be triggered by a call to
sort()
collection
The collection after the model is added.
operation object
A map containing the following keys:
merge (boolean)
add (boolean)
remove (boolean)
The values in this map indicate the operation that occurred that triggered the event. If this event was triggered by invocation of
sort
, this map will be empty.
Event | Model | Collection |
---|---|---|
sort |
Change
expModelA.on('change', function (model) {
...
});
expCollA.on('change', function (model) {
...
});
This event is triggered on both the model that was changed, and the collection that the model is in.
- model
- The model that was changed.
Event | Model | Collection |
---|---|---|
change |
Reset
expCollA.on('reset', function (collection, obj) {
...
});
expCollA.reset();
The reset event is invoked by the reset()
method. This method
accepts an optional parameter that is the list of models used to replace the
collection. The callback function receives 2 parameters:
- collection
- The collection after the reset operation is completed.
- options
This object has the
previousModels
property that holds the models that were replaced by thereset()
operation.
Event | Model | Collection |
---|---|---|
reset |
(2023 February note: The script below was supposed to update the tables in this page. But since the change to Docusaurus, the needed scripts are no longer available on the page so the code does not work anymore. They are left here for posterity.)
<script src="/js/lib/jquery.min.js"></script>
<script src="/js/lib/underscore.min.js"></script>
<script src="/js/lib/backbone.min.js"></script>
$(document).ready(function () {
var tick = '✓';
var ExperimentModel = Backbone.Model.extend({
defaults: {
name: null
},
validate: function (attrs) {
if (!attrs.name) {
return 'name is required';
}
}
});
var ExperimentCollection = Backbone.Collection.extend({
model: ExperimentModel
});
console.info('Instantiating ExperimentModel A', expModelA);
var expModelA = new ExperimentModel({
id: 'a',
name: 'Alpha'
});
console.info('Instantiating ExperimentCollection A', expCollA);
var expCollA = new ExperimentCollection();
expCollA.comparator = 'name';
expModelA.on('change', function (m) {
console.log('Model: change', m.toJSON(), arguments);
$('.change-model').html(tick);
});
expModelA.on('sort', function () {
console.log('Model: sort', arguments);
});
expModelA.on('reset', function () {
console.log('Model: reset', arguments);
});
expModelA.on('update', function () {
console.log('Model: update', arguments);
$('.update-model').html(tick);
});
expModelA.on('add', function (m, c, o) {
console.log('Model: add', m.toJSON(), c.length, o);
$('.add-model').html(tick);
});
expModelA.on('remove', function (m, c, o) {
console.log('Model: remove', m.toJSON(), c.length, o);
$('.remove-model').html(tick);
});
expCollA.on('change', function (m) {
console.log('Collection: change', m.toJSON(), arguments);
$('.change-collection').html(tick);
});
expCollA.on('sort', function (c, o) {
console.log('Collection: sort', c.length, o);
$('.sort-collection').html(tick);
});
expCollA.on('reset', function (c, o) {
console.log('Collection: reset', c.length, o);
$('.reset-collection').html(tick);
});
expCollA.on('update', function (c, o) {
console.log('Collection: update', c.length, o);
$('.update-collection').html(tick);
if (o.add) { console.log('ADD'); } else { console.log('REMOVE'); }
});
expCollA.on('add', function (m, c, o) {
console.log('Collection: add', m.toJSON(), c.length, o);
$('.add-collection').html(tick);
});
expCollA.on('remove', function (m, c, o) {
console.log('Collection: remove', m.toJSON(), c.length, o);
$('.remove-collection').html(tick);
});
//Steps
console.info('Adding model A to collection A');
expCollA.add(expModelA);
console.info('Setting name on model A');
expModelA.set('name', 'Experiment A');
console.info('Removing model A from collection A');
expCollA.remove(expModelA);
console.info('Unsetting name on model A');
expModelA.unset('name');
console.log('Adding model A back to collection A');
expCollA.add(expModelA);
console.info('Changing name of model A');
expModelA.set('name', 'Aloha');
console.info('Resetting collection A');
expCollA.reset([
new ExperimentModel({ id: 'd', name: 'Delta' }),
new ExperimentModel({ id: 'c', name: 'Charlie' }),
new ExperimentModel({ id: 'b', name: 'Bravo' })
]);
console.warn('Final length:', expCollA.length);
});