Skip to content

Backbone Collections — Managing Groups of Models

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Backbone Collections. We cover key concepts, practical examples, and best practices to help you master this topic.

Backbone Collections are ordered sets of Models. They provide methods for adding, removing, sorting, filtering, and syncing groups of related Models. Collections fire events when items change, making it easy to keep the UI in sync.

What You'll Learn

You'll learn how to define Collections, populate them with Models, listen for collection-level events, use built-in methods, and fetch data from REST endpoints.

Why It Matters

Applications rarely work with single data items. Collections manage the list of items — search results, task lists, message threads — and provide the operations needed to manipulate them as a group.

Real-World Use

A SIEM dashboard displays a list of security alerts as a Collection. When new alerts arrive from the server, the Collection updates automatically. The View re-renders to show the latest threats without page reload.

flowchart LR
    A[Collection] --> B[Model 1]
    A --> C[Model 2]
    A --> D[Model 3]
    B --> E[Event: change]
    C --> E
    D --> E
    E --> F[View re-renders]

Defining a Collection

Specify the Model class and optional properties. The Collection knows what type of Models it holds.

var Task = Backbone.Model.extend({
  defaults: { title: '', completed: false }
});

var TaskList = Backbone.Collection.extend({
  model: Task
});

var tasks = new TaskList();
tasks.add({ title: 'Learn Backbone' });
tasks.add({ title: 'Build an app', completed: true });

console.log('Collection size:', tasks.length);
console.log('First task:', tasks.at(0).get('title'));
console.log('Last task:', tasks.at(1).get('title'));

Expected output:

Collection size: 2
First task: Learn Backbone
Last task: Build an app

Listening to Collection Events

Collections fire events when models are added, removed, changed, or when the collection itself is sorted or reset.

var Task = Backbone.Model.extend({
  defaults: { title: '', completed: false }
});
var TaskList = Backbone.Collection.extend({ model: Task });

var tasks = new TaskList();

tasks.on('add', function(model) {
  console.log('Added:', model.get('title'));
});

tasks.on('remove', function(model) {
  console.log('Removed:', model.get('title'));
});

tasks.on('change:completed', function(model) {
  console.log('Status changed:', model.get('title'), model.get('completed'));
});

var task1 = tasks.add({ title: 'Write docs', id: 1 });
var task2 = tasks.add({ title: 'Review PR', id: 2 });

tasks.remove(task1);
task2.set('completed', true);

Expected output:

Added: Write docs
Added: Review PR
Removed: Write docs
Status changed: Review PR true

Populating Collections

There are three ways to populate a Collection: add for appending, push and unshift for array-like behavior, and reset to replace all contents.

var Task = Backbone.Model.extend({ defaults: { title: '' } });
var TaskList = Backbone.Collection.extend({ model: Task });

var tasks = new TaskList();

// add — appends or merges
tasks.add({ title: 'Task A', id: 1 });
tasks.add({ title: 'Task B', id: 2 });

// push — appends to end
tasks.push({ title: 'Task C', id: 3 });

// unshift — prepends to beginning
tasks.unshift({ title: 'Task 0', id: 0 });

// reset — replaces all models
tasks.reset([
  { title: 'New start', id: 100 },
  { title: 'Fresh list', id: 101 }
]);

console.log('After reset:', tasks.pluck('title'));

Expected output:

After reset: ['New start', 'Fresh list']

Fetching from Server

fetch() sends a GET request to the Collection URL and calls reset() or set() with the response data.

var Task = Backbone.Model.extend({ defaults: { title: '' } });
var TaskList = Backbone.Collection.extend({
  model: Task,
  url: '/api/tasks'
});

var tasks = new TaskList();

tasks.on('sync', function() {
  console.log('Collection synced. Total tasks:', tasks.length);
  tasks.each(function(task) {
    console.log('-', task.get('title'));
  });
});

tasks.fetch();

Expected output (assuming server returns [{id:1,title:"Task 1"},{id:2,title:"Task 2"}]):

Collection synced. Total tasks: 2
- Task 1
- Task 2

Getting Models from Collections

Retrieve models by index, ID, or by matching attribute values.

var Task = Backbone.Model.extend({ defaults: { title: '' } });
var TaskList = Backbone.Collection.extend({ model: Task });

var tasks = new TaskList([
  { id: 1, title: 'Alpha', priority: 'high' },
  { id: 2, title: 'Beta', priority: 'low' },
  { id: 3, title: 'Gamma', priority: 'high' }
]);

console.log('By index:', tasks.at(0).get('title'));
console.log('By ID:', tasks.get(2).get('title'));
console.log('First high priority:', tasks.findWhere({ priority: 'high' }).get('title'));
console.log('All high priority:', tasks.where({ priority: 'high' }).length);

Expected output:

By index: Alpha
By ID: Beta
First high priority: Alpha
All high priority: 2

Sorting Collections

Collections have a comparator property that defines sort order. It can be a string (attribute name) or a function.

var Task = Backbone.Model.extend({ defaults: { title: '', priority: 0 } });
var TaskList = Backbone.Collection.extend({
  model: Task,
  comparator: 'priority'  // Sort by priority ascending
});

var tasks = new TaskList([
  { title: 'High priority', priority: 3 },
  { title: 'Low priority', priority: 1 },
  { title: 'Medium priority', priority: 2 }
]);

console.log('Sorted:', tasks.pluck('title'));

// Custom comparator function
var TaskListCustom = Backbone.Collection.extend({
  model: Task,
  comparator: function(model) {
    return -model.get('priority');  // Descending
  }
});

var tasks2 = new TaskListCustom([
  { title: 'Low', priority: 1 },
  { title: 'High', priority: 3 }
]);

console.log('Custom sort:', tasks2.pluck('title'));

Expected output:

Sorted: ['Low priority', 'Medium priority', 'High priority']
Custom sort: ['High', 'Low']

Common Mistakes

  1. Not specifying the model property. Without model, collections accept plain objects instead of Model instances. Events and methods like get() will not work correctly.
  2. Mutating model attributes directly within a collection. Changing models[0].attributes.title does not fire events. Use model.set() instead.
  3. Using fetch() without setting a url. Backbone throws an error if it does not know where to fetch from. Always set url or urlRoot.
  4. Assuming add() replaces duplicates by default. By default, add() skips models with duplicate IDs. Use {merge: true} to update existing models instead.
  5. Forgetting that reset() removes all existing event listeners. Models replaced by reset() are removed. Listeners on old models stop working.

Practice Questions

  1. How do you define what type of Model a Collection holds?
  2. What events does a Collection fire?
  3. How do you retrieve a Model by its ID from a Collection?
  4. What is the difference between add() and push()?
  5. Challenge: Create a SortedTaskList that maintains tasks sorted by due date (ascending). Add three tasks with different dates and verify the order.

FAQ

Can a Collection hold different Model types?

Not directly. A Collection holds one Model type. For mixed types, use a plain array or create a parent Model that contains children.

What is the difference between `fetch()` and `reset()`?

fetch() loads data from the server. reset() replaces all models with local data, no server request.

How do I chain Collection methods?

Most collection methods return this, enabling chaining: collection.add(model).sort().each(fn).

Can I use a Collection without a Model class?

Yes, but you lose Model methods like save(), validate(), and typed event handling.

How do I get the index of a Model in a Collection?

Use collection.indexOf(model) to get the position.

Mini Project

Create a Playlist Collection that holds Song Models (title, artist, duration, rating). Add methods: averageRating(), songsByArtist(artist), totalDuration(), and topRated(n). Populate with 5 songs and call each method.

What's Next

Now that you understand Collections, learn Backbone Collection Methods for advanced querying and manipulation. Then study Backbone Views for rendering data to the DOM.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro