Write, Run & Share Backbone.js code online using OneCompiler's Backbone.js online editor for free. It's one of the robust, feature-rich online editors for Backbone.js. Getting started with the OneCompiler's Backbone.js online editor is really simple and pretty fast. The editor shows sample boilerplate code when you choose language as 'Backbone.js' and start writing code to learn and test online without worrying about tedious process of installation.
Backbone.js is a lightweight JavaScript library that provides structure to web applications through models, collections, views, and routers. It follows the MVC (Model-View-Controller) pattern and helps organize code by separating data logic from presentation. Backbone depends on Underscore.js and optionally jQuery, making it a minimal yet powerful framework for building single-page applications.
Models in Backbone represent data and business logic, providing methods for getting, setting, and validating attributes. Each model can define default values, computed properties, and validation rules. When model attributes change, Backbone automatically triggers events that views can listen to for updating the UI. Models can also sync with a server via RESTful APIs using built-in persistence methods.
// Define a model
var Person = Backbone.Model.extend({
// Default attribute values
defaults: {
name: "Unknown",
age: 0,
email: "",
},
// Initialize is called when model is created
initialize: function () {
console.log("Person created")
this.on("change", function () {
console.log("Attributes changed")
})
},
// Validation (return error message if invalid)
validate: function (attrs) {
if (attrs.age < 0) {
return "Age cannot be negative"
}
if (!attrs.name) {
return "Name is required"
}
},
// Custom methods
getFullInfo: function () {
return this.get("name") + " (" + this.get("age") + ")"
},
})
// Create instance
var person = new Person({ name: "John", age: 30 })
// Get and set attributes
person.get("name") // 'John'
person.set("age", 31) // Triggers 'change' and 'change:age' events
person.set({ name: "Jane", age: 25 }) // Set multiple
// Other methods
person.has("email") // false (empty string is falsy)
person.unset("email") // Remove attribute
person.clear() // Remove all attributes
person.toJSON() // Get all attributes as object
person.isValid() // Check validation
Collections are ordered sets of models that provide methods for managing and iterating over groups of data. They fire events when models are added, removed, or changed, making it easy to keep views synchronized. Collections can fetch data from a server and automatically create model instances. Underscore.js methods are mixed in, providing powerful iteration and filtering capabilities.
// Define a collection
var People = Backbone.Collection.extend({
model: Person,
url: "/api/people",
// Comparator for sorting (by age ascending)
comparator: "age",
// Or as function: comparator: function(model) { return model.get('age'); }
initialize: function () {
this.on("add", function (model) {
console.log("Added:", model.get("name"))
})
},
// Custom methods
getAdults: function () {
return this.filter(function (person) {
return person.get("age") >= 18
})
},
})
// Create collection
var people = new People([
{ name: "John", age: 30 },
{ name: "Jane", age: 25 },
])
// Add and remove models
people.add({ name: "Bob", age: 40 })
people.add([{ name: "Alice" }, { name: "Eve" }])
people.remove(person) // Remove specific model
people.reset([]) // Replace all models
// Access models
people.at(0) // Model at index
people.get(modelId) // Model by ID
people.length // Number of models
people.first() // First model
people.last() // Last model
// Underscore methods (all available)
people.each(function (person) {
console.log(person.get("name"))
})
people.map(function (p) {
return p.get("name")
})
people.filter(function (p) {
return p.get("age") > 25
})
people.find(function (p) {
return p.get("name") === "John"
})
people.where({ age: 30 }) // All matching
people.findWhere({ age: 30 }) // First matching
people.pluck("name") // ['John', 'Jane', 'Bob']
people.sortBy("age")
Views in Backbone handle UI rendering and user interaction, connecting models/collections to the DOM. Each view has an el property representing its DOM element and a render() method for updating the display. Views can listen to model/collection events to automatically re-render when data changes. Event delegation handles user interactions like clicks and form submissions.
// Define a view
var PersonView = Backbone.View.extend({
tagName: "div", // Creates <div> element
className: "person-card", // CSS class
id: "person-1", // Element ID
// Or use existing element: el: '#existing-element'
// Template (using Underscore templates)
template: _.template(
'<h2><%= name %></h2><p>Age: <%= age %></p><button class="delete">Delete</button>'
),
// DOM events (delegated to this.el)
events: {
"click .delete": "onDelete",
"click h2": "onNameClick",
"submit form": "onSubmit",
},
// Called when view is created
initialize: function () {
// Listen to model changes
this.listenTo(this.model, "change", this.render)
this.listenTo(this.model, "destroy", this.remove)
},
// Render the view
render: function () {
this.$el.html(this.template(this.model.toJSON()))
return this // Enable chaining
},
// Event handlers
onDelete: function (e) {
e.preventDefault()
this.model.destroy()
},
onNameClick: function () {
console.log("Clicked:", this.model.get("name"))
},
})
// Create and render view
var personView = new PersonView({ model: person })
$("#app").append(personView.render().el)
// View for collection
var PeopleView = Backbone.View.extend({
el: "#people-list",
initialize: function () {
this.listenTo(this.collection, "add", this.addOne)
this.listenTo(this.collection, "reset", this.render)
},
render: function () {
this.$el.empty()
this.collection.each(this.addOne, this)
return this
},
addOne: function (person) {
var view = new PersonView({ model: person })
this.$el.append(view.render().el)
},
})
var peopleView = new PeopleView({ collection: people })
Backbone's event system provides a way for objects to communicate through custom events. Any object can mix in Backbone.Events to trigger and listen to events. Views use listenTo() to listen to model/collection events, which automatically cleans up when the view is removed. This decoupled communication pattern keeps components independent and testable.
// Model events
person.on("change", function () {
console.log("Any attribute changed")
})
person.on("change:name", function (model, value) {
console.log("Name changed to:", value)
})
// Collection events
people.on("add", function (model, collection, options) {
console.log("Model added")
})
people.on("remove", function (model, collection, options) {
console.log("Model removed")
})
people.on("reset", function (collection, options) {
console.log("Collection reset")
})
people.on("sort", function (collection) {
console.log("Collection sorted")
})
// Common events: change, change:[attr], add, remove, reset, sort, destroy, sync, error
// Listen from another object (auto-cleanup with listenTo)
this.listenTo(person, "change", this.handleChange)
this.listenTo(people, "add remove", this.handleUpdate)
// Stop listening
person.off("change") // Remove all change listeners
person.off("change", callback) // Remove specific listener
this.stopListening() // Stop listening to all (in views)
// Trigger custom events
person.trigger("custom:event", { data: "payload" })
// Create custom event-enabled object
var dispatcher = _.extend({}, Backbone.Events)
dispatcher.on("notify", function (msg) {
console.log(msg)
})
dispatcher.trigger("notify", "Hello!")
// Once: listen to event only once
person.once("change", function () {
console.log("First change only")
})
The router maps URLs to functions, enabling browser history and deep linking in single-page applications. Routes can include dynamic segments and splats for capturing URL parameters. When a route matches, the corresponding handler function is called. The router integrates with Backbone.history to monitor URL changes and trigger appropriate handlers.
// Define router
var AppRouter = Backbone.Router.extend({
// Route patterns to handler methods
routes: {
"": "home", // Empty route (home)
about: "about", // /about
users: "userList", // /users
"users/:id": "userDetail", // /users/123 (dynamic segment)
"users/:id/posts/:postId": "post", // Multiple segments
"search/:query": "search",
"files/*path": "files", // Splat (matches rest of URL)
"*notFound": "notFound", // Catch-all
},
initialize: function () {
console.log("Router initialized")
},
home: function () {
console.log("Home page")
},
about: function () {
console.log("About page")
},
userDetail: function (id) {
console.log("User ID:", id)
},
post: function (userId, postId) {
console.log("User:", userId, "Post:", postId)
},
search: function (query) {
console.log("Search:", decodeURIComponent(query))
},
files: function (path) {
console.log("File path:", path)
},
notFound: function (path) {
console.log("404 Not Found:", path)
},
})
// Create router and start history
var router = new AppRouter()
Backbone.history.start() // Start monitoring URL changes
// Backbone.history.start({pushState: true}); // Use HTML5 pushState
// Navigate programmatically
router.navigate("users/123") // Change URL only
router.navigate("users/123", { trigger: true }) // Change URL and trigger handler
router.navigate("users/123", { replace: true }) // Replace history entry
Backbone models and collections sync with a server via RESTful APIs using the fetch(), save(), and destroy() methods. By default, Backbone uses jQuery's AJAX for HTTP requests with JSON data. You can override sync() to customize server communication, use different backends, or add authentication. The urlRoot and url properties define the endpoint for API requests.
// Model with URL
var User = Backbone.Model.extend({
urlRoot: "/api/users",
// URL pattern: GET/POST /api/users, GET/PUT/DELETE /api/users/:id
// Optional: customize URL
url: function () {
return "/api/users/" + this.id + "/profile"
},
})
// Fetch model from server
var user = new User({ id: 1 })
user.fetch({
success: function (model, response) {
console.log("Loaded:", model.toJSON())
},
error: function (model, response) {
console.log("Error:", response.status)
},
})
// Save model (POST for new, PUT for existing)
user.save(
{ name: "John" },
{
success: function (model) {
console.log("Saved")
},
wait: true, // Wait for server before updating model
patch: true, // Use PATCH instead of PUT (send only changed attributes)
}
)
// Delete model
user.destroy({
success: function () {
console.log("Deleted")
},
wait: true,
})
// Collection fetch
var Users = Backbone.Collection.extend({
model: User,
url: "/api/users",
})
var users = new Users()
users.fetch({
data: { page: 1, limit: 10 }, // Query parameters
reset: true, // Fire 'reset' instead of 'add' events
})
// Override sync for custom behavior
Backbone.sync = function (method, model, options) {
// method: 'create', 'read', 'update', 'delete'
console.log("Syncing:", method)
// Add auth header
options.headers = { Authorization: "Bearer token" }
// Call default sync
return Backbone.sync.call(this, method, model, options)
}
Backbone works with any templating library, but commonly uses Underscore.js templates built-in. Templates separate HTML structure from JavaScript logic, making views easier to maintain. You can precompile templates for better performance and use template helpers for formatting data. External template files can be loaded via AJAX or bundled with build tools.
// Underscore.js template basics
var template = _.template("<h1><%= title %></h1><p><%- content %></p>")
// <%= %> interpolates value
// <%- %> escapes HTML (prevents XSS)
// <% %> executes JavaScript
var html = template({
title: "Hello",
content: '<script>alert("xss")</script>',
})
// Template with logic
var listTemplate = _.template(`
<ul>
<% items.forEach(function(item) { %>
<li class="<%= item.active ? 'active' : '' %>">
<%= item.name %>
</li>
<% }); %>
</ul>
`)
var html = listTemplate({
items: [{ name: "One", active: true }, { name: "Two" }],
})
// Using templates in views
var ItemView = Backbone.View.extend({
template: _.template($("#item-template").html()),
render: function () {
this.$el.html(this.template(this.model.toJSON()))
return this
},
})
// Template in HTML
// <script type="text/template" id="item-template">
// <h2><%= name %></h2>
// <p><%= description %></p>
// </script>
// Configure template settings
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g, // {{ variable }}
escape: /\{\{-(.+?)\}\}/g, // {{- escaped }}
evaluate: /\{\%(.+?)\%\}/g, // {% code %}
}