Introduction
In this article, we will discuss about backbone.js collections. We will see how we can use collections to manipulate a group of models and how we can use restful API to easily fetch and save collections.
Background
Every application needs to create a collection of models which can be ordered, iterated and perhaps sorted and searched when a need arises. Keeping this in mind, backbone also comes with a collection type which makes dealing with collection of models fairly easy and straight forward.
Link to complete series:
- BackBone Tutorial – Part 1: Introduction to Backbone.Js[^]
- BackBone Tutorial – Part 2: Understanding the basics of Backbone Models[^]
- BackBone Tutorial – Part 3: More about Backbone Models[^]
- BackBone Tutorial – Part 4: CRUD Operations on BackboneJs Models using HTTP REST Service[^]
- BackBone Tutorial – Part 5: Understanding Backbone.js Collections[^]
- BackBone Tutorial – Part 6: Understanding Backbone.js Views[^]
- BackBone Tutorial – Part 7: Understanding Backbone.js Routes and History[^]
- BackBone Tutorial – Part 8: Understanding Backbone.js Events[^]
Using the Code
Let us start looking at the backbone collections in details.
Creating a Collection
Creating a backbone collection is similar to creating a model. We just need to extend
the backbone's collection class to create our own collection. Let us continue working with the same example where we created a Book
model and let's try to create a simple BooksCollection
.
var BooksCollection = Backbone.Collection.extend({
});
This collection will hold the Book
model we have created in our previous articles.
var Book = Backbone.Model.extend({
defaults: {
ID: "",
BookName: ""
},
idAttribute: "ID",
urlRoot: 'http://localhost:51377/api/Books'
});
Specifying the Model for a Collection
To specify which model this collection should hold, we need to specify/override the model
property of the collection
class.
var BooksCollection = Backbone.Collection.extend({
model: Book,
});
Once we specify the model
property of a collection
, what will happen internally is that whenever we create this collection
, internally, it will create an array of the specified models. Then all the operations on this collection
object will result in the actual operations on that array.
Instantiating a Collection
A collection
can be instantiated by using the new
keyword. We can create an empty collection
and then add the model
objects to it later or we can pass a few model
objects in the collection
while creating it.
var collection1 = new BooksCollection();
var book1 = new Book({ ID: 1, BookName: "Book 1" });
var book2 = new Book({ ID: 2, BookName: "Book 2" });
var collection2 = new BooksCollection([book1, book2]);
Adding Models to Collection
To add an item to a collection
, we can use the add
method on the collection
. The important thing to notice here is that if the item with the same id
exists in the collection
, the add
will simply be ignored.
var book3 = new Book({ ID: 3, BookName: "Book 3" });
collection2.add(book3);
Now there might be a scenario where we actually want to update an existing added model in a collection. If that is the case, then we need to pass the {merge: true}
option in the add
function.
var book3 = new Book({ ID: 3, BookName: "Book 3" });
collection2.add(book3);
var book3_changed = new Book({ ID: 3, BookName: "Changed Model" });
collection2.add(book3_changed, { merge: true });
Another important point to consider here is that the collection
keeps a shallow copy of the actual models. So if we change a model attribute after adding it to a collection
, the attribute value will also get changed inside the collection
.
Also, if we want to add multiple models, we can do that by passing the model array in the add
method.
var book4 = new Book({ ID: 4, BookName: "Book 4" });
var book5 = new Book({ ID: 5, BookName: "Book 5" });
collection2.add([book4, book5]);
It is also possible to add the model at a specific index in the collection. To do this, we need to pass the {at: location}
in the add
options.
var book0 = new Book({ ID: 0, BookName: "Book 0" });
collection2.add(book0, {at:0});
Note: push
and unshift
function can also be used to add models to collection.
Removing Models from Collection
To remove the model from the collection, we just need to call the remove
method on the collection. The remove
method simply removes this model from the collection.
collection2.remove(book0);
Also, if we want to empty the model, we can call the reset
method on the collection.
collection1.reset();
It is also possible to reset a collection and populate it with new models by passing an array of models in the reset
function.
collection2.reset([book4, book5]);
Note: pop
and shift
function can also be used to remove model
from collection
.
Finding the Number of Items in Collection
The total number of items in a collection can be found using the length
property.
var collection2 = new BooksCollection([book1, book2]);
console.log(collection2.length);
Retrieving Models from Collection
To retrieve a model from a specific location, we can use the at
function by passing a 0
based index.
var bookRecieved = collection2.at(3);
Alternatively, to get the index of a known model in the collection, we can use the indexOf
method.
var index = collection2.indexOf(bookRecieved);
We can also retrieve a model from a collection if we know its id
or cid
. This can be done by using the get
function.
var bookFetchedbyId = collection2.get(2);
var bookFetchedbyCid = collection2.get("c3");
If we want to iterate through all the models in a collection, we can simply use the classic for
loop or the each
function provided by collections which is very similar to the foreach
loop of underscore.js.
for (var i = 0; i < collection2.length; ++i) {
console.log(collection2.at(i).get("BookName"));
}
collection2.each(function (item, index, all) {
console.log(item.get("BookName"));
});
Listening to Collection Events
Backbone collection
raises events whenever an item is added, removed to updated in the collection. We can subscribe to these events by listening to add
, remove
and change
event respectively. Let us subscribe to these events in our model to see how this can be done.
var BooksCollection = Backbone.Collection.extend({
model: Book,
initialize: function () {
this.on('add', function(model) {
console.log('something got added');
});
this.on('remove', function(model) {
console.log('something got removed');
});
this.on('change', function(model) {
console.log('something got changed');
});
},
});
The Set Function
The set
function can be used to update all the items in a model. If we use set
function, it will check for all the existing models and the models being passed in set
. If any new model is found in the models being passed, it will be added. If some are not present in the new models list, they will be removed. If there are same models, they will be updated.
var collection3 = new BooksCollection();
collection3.add(book1);
collection3.add(book2);
collection3.add(book3);
collection3.set([book1, { ID: 3, BookName: "test sort"}, book5]);
The above shown set function will call remove for book2
, change for book3
and add for book5
.
Sorting a Collection
Backbone keeps all the models in the collection
in a sorted order. We can call the sort
function to forcefully sort it again but the models are always stored in sorted order. By default, these items are sorted in the order they are added to the collection
. But we can customize this sorting behavior by providing a simple comparator to our collection
.
var BooksCollection = Backbone.Collection.extend({
model: Book,
comparator: function (model) {
return model.get("ID");
},
});
What this comparator does is that it overrides the default sorting behavior by specifying the attribute that should be used for sorting. We can even use a custom expression in this comparator too.
Fetch Collection using HTTP REST Service
To be able to fetch
the collection
from the server, we need to specify the url
for the API that returns the collection
.
var BooksCollection = Backbone.Collection.extend({
model: Book,
url: "http://localhost:51377/api/Books",
});
Now to fetch
the collection
from the server, let's call the fetch
function.
var collection4 = new BooksCollection();
collection4.fetch();
Save Collection using HTTP REST Service
Let's see how we can save the items of a collection on the server.
var collection4 = new BooksCollection();
collection4.fetch({
success: function (collection4, response) {
collection4.each(function (item, index, all) {
item.set("BookName", item.get("BookName") + "_updated");
item.save();
});
}
});
In the above code, we are calling save
on each model
object. This can be improved by either overriding the sync
function on a collection
or perhaps creating a wrapper model for collection
and saving the data using that.
Note: The web API code can be downloaded from the previous article of the series.
Point of interest
In this article, we have discussed about the backbone collections. This has been written from a beginner's perspective. I hope this has been informative.
History
- 21st July, 2014: First version