http://backbonejs.org/
Models, Views & Collections
Routing with URLs
The Router detects changes to the URL. Pressing the "Back" button, and it will tell your application exactly where you are now.
Simple backbone app, Developing Backbone.js Applications
Model.set()
var Todo = Backbone.Model.extend({
// Default todo attribute values
defaults: {
title: '',
completed: false
}
});
// Setting the value of attributes via instantiation
var myTodo = new Todo({
title: "Set through instantiation."
});
// Set single attribute value at a time through Model.set():
myTodo.set("title", "Title attribute set through Model.set().");
// Set map of attributes through Model.set():
myTodo.set({
title: "Both attributes set through Model.set().",
completed: true
});
What is el? - The central property of a view is el.
What is el and how is it defined?
el is basically a reference to a DOM element and all views must have one. Views can use el to compose their element’s content and then insert it into the DOM all at once, which makes for faster rendering because the browser performs the minimum required number of reflows and repaints.
If you want to create a new element for your view, set any combination of the following properties on the view: tagName, id, and className.
Example creates a ul element with id and class attributes:
Collections - Collections are sets of Models and are created by extending Backbone.Collection.
Adding and Removing Models
Retrieving Models
Underscore.js utility functions
forEach: iterate over collections
sortBy(): sort a collection on a specific attribute
map(): iterate through a collection, mapping each value through a transformation function
pluck(): extract a specific attribute
filter(): filter a collection
groupBy(): group a collection into groups of like items
// create groups of completed and incomplete models
pick(): extract a set of attributes from a model
omit(): extract all attributes from a model except those listed
keys() and values(): get lists of attribute names and values
pairs(): get list of attributes as [key, value] pairs
invert(): create object in which the values are keys and the attributes are values
Chainable API
RESTful Persistence
Saving models to the server
A model’s validate() method is called automatically by save() and will trigger an invalid event on the model if validation fails.
Deleting models from the server
Routers
http://example.com/#about
http://example.com/#search/seasonal-horns/page2
Backbone.history - This will automatically handle routes that have been defined and trigger callbacks when they’ve been accessed.
Backbone’s Sync API
Backbone.emulateHTTP = false; // set to true if server cannot handle HTTP PUT or HTTP DELETE
Backbone.emulateJSON = false; // set to true if server cannot handle application/json requests
Backbone.sync
The sync method is called with three parameters:
method: One of create, update, patch, delete, or read
model: The Backbone model object
options: May include success and error methods
Implementing a new sync method can use the following pattern:
Nutritionix Health Tracker Project
Develop a single page app that tracks the user's calorie intake, and optionally, other health-related metrics. Typing food names into the search field will display a list of matching foods as provided by the health API. Users will be able to select an item from the list, and the item will be added to the list of foods the user is tracking. The total calorie count will also update to reflect the new daily total.
https://developer.nutritionix.com/docs/v1_1
Project Code
Models, Views & Collections
var Books = Backbone.Collection.extend({
url: '/books'
});
Methods:
GET /books/ .... collection.fetch();
POST /books/ .... collection.create();
GET /books/1 ... model.fetch();
PUT /books/1 ... model.save();
DEL /books/1 ... model.destroy();
Example
{
"page": 1,
"limit": 10,
"total": 2,
"books": [
{"id": 1, "title": "Pride and Prejudice"},
{"id": 4, "title": "The Great Gatsby"}
]
}
var Books = Backbone.Collection.extend({
url: '/books',
parse: function(data) {
return data.books;
}
});
url: '/books'
});
Methods:
GET /books/ .... collection.fetch();
POST /books/ .... collection.create();
GET /books/1 ... model.fetch();
PUT /books/1 ... model.save();
DEL /books/1 ... model.destroy();
Example
{
"page": 1,
"limit": 10,
"total": 2,
"books": [
{"id": 1, "title": "Pride and Prejudice"},
{"id": 4, "title": "The Great Gatsby"}
]
}
var Books = Backbone.Collection.extend({
url: '/books',
parse: function(data) {
return data.books;
}
});
Routing with URLs
The Router detects changes to the URL. Pressing the "Back" button, and it will tell your application exactly where you are now.
Simple backbone app, Developing Backbone.js Applications
Model.set()
var Todo = Backbone.Model.extend({
// Default todo attribute values
defaults: {
title: '',
completed: false
}
});
// Setting the value of attributes via instantiation
var myTodo = new Todo({
title: "Set through instantiation."
});
// Set single attribute value at a time through Model.set():
myTodo.set("title", "Title attribute set through Model.set().");
// Set map of attributes through Model.set():
myTodo.set({
title: "Both attributes set through Model.set().",
completed: true
What is el? - The central property of a view is el.
What is el and how is it defined?
el is basically a reference to a DOM element and all views must have one. Views can use el to compose their element’s content and then insert it into the DOM all at once, which makes for faster rendering because the browser performs the minimum required number of reflows and repaints.
If you want to create a new element for your view, set any combination of the following properties on the view: tagName, id, and className.
Example creates a ul element with id and class attributes:
var TodosView = Backbone.View.extend({
tagName: 'ul', // required, but defaults to 'div' if not set
className: 'container', //optional
id: 'todos' // optional
});
var todosView = new TodosView();
console.log(todosView.el); // logs <ul id="todos" class="container"></ul>
eland() - The view.$el property is equivalent to $(view.el) and view.$(selector) is equivalent to $(view.el).find(selector).tagName: 'ul', // required, but defaults to 'div' if not set
className: 'container', //optional
id: 'todos' // optional
});
var todosView = new TodosView();
console.log(todosView.el); // logs <ul id="todos" class="container"></ul>
Collections - Collections are sets of Models and are created by extending Backbone.Collection.
Adding and Removing Models
var Todo = Backbone.Model.extend({
defaults: {
title: '',
completed: false
}
});
var TodosCollection = Backbone.Collection.extend({
model: Todo
});
var a = new Todo({ title: 'Jamaica.'}),
b = new Todo({ title: 'China.'}),
c = new Todo({ title: 'Disneyland.'});
var todos = new TodosCollection([a,b]); // todos.length = > 2
todos.add(c); // todos.length = > 3
todos.remove([a,b]); // todos.length = > 1
todos.remove(c); // todos.length = > 0
defaults: {
title: '',
completed: false
}
});
var TodosCollection = Backbone.Collection.extend({
model: Todo
});
var a = new Todo({ title: 'Jamaica.'}),
b = new Todo({ title: 'China.'}),
c = new Todo({ title: 'Disneyland.'});
var todos = new TodosCollection([a,b]); // todos.length = > 2
todos.add(c); // todos.length = > 3
todos.remove([a,b]); // todos.length = > 1
todos.remove(c); // todos.length = > 0
Retrieving Models
var myTodo = new Todo({title:'Read the whole book', id: 2});
// pass array of models on collection instantiation
var todos = new TodosCollection([myTodo]);
var todo2 = todos.get(2);
// Models, as objects, are passed by reference
console.log(todo2 === myTodo); // true
var todo3 = todos.get(3); //undefined
// pass array of models on collection instantiation
var todos = new TodosCollection([myTodo]);
var todo2 = todos.get(2);
// Models, as objects, are passed by reference
console.log(todo2 === myTodo); // true
var todo3 = todos.get(3); //undefined
Underscore.js utility functions
forEach: iterate over collections
todos.forEach(function(model){
console.log(model.get('title'));
});
console.log(model.get('title'));
});
sortBy(): sort a collection on a specific attribute
var sortedByAlphabet = todos.sortBy(function (todo) {
return todo.get("title").toLowerCase();
});
return todo.get("title").toLowerCase();
});
map(): iterate through a collection, mapping each value through a transformation function
var count = 1;
console.log(todos.map(function(model){
return count++ + ". " + model.get('title');
}));
console.log(todos.map(function(model){
return count++ + ". " + model.get('title');
}));
pluck(): extract a specific attribute
var names = collection.pluck('title'); // ['Belgium', 'China', 'Austria']
filter(): filter a collection
var Todos = Backbone.Collection.extend({
model: Todo,
filterById: function(ids){
return this.filter(
function(c) {
return _.contains(ids, c.id);
})
}
});
model: Todo,
filterById: function(ids){
return this.filter(
function(c) {
return _.contains(ids, c.id);
})
}
});
groupBy(): group a collection into groups of like items
// create groups of completed and incomplete models
var byCompleted = todos.groupBy('completed');
var completed = new Backbone.Collection(byCompleted[true]);
console.log(completed.pluck('title')); //["Austria."]
var completed = new Backbone.Collection(byCompleted[true]);
console.log(completed.pluck('title')); //["Austria."]
pick(): extract a set of attributes from a model
var todo = new Todo({title: 'Austria.'}); // todo.pick('title') => {title: "Austria"}
omit(): extract all attributes from a model except those listed
console.log(todo.omit('title')) // {completed: false}
keys() and values(): get lists of attribute names and values
todo.keys() => ["title", "completed"]
todo.values() => ["Austria.", false]
todo.values() => ["Austria.", false]
pairs(): get list of attributes as [key, value] pairs
var pairs = todo.pairs();
pairs[0] => ["title", "Austria."]
pairs[1] = > ["completed", false]
pairs[0] => ["title", "Austria."]
pairs[1] = > ["completed", false]
invert(): create object in which the values are keys and the attributes are values
todo.invert()) = > {'go to Austria.': 'title', 'false': 'completed'}
Chainable API
var collection = new Backbone.Collection([
{ name: 'Tim', age: 5 },
{ name: 'Ida', age: 26 },
{ name: 'Rob', age: 55 }
]);
var filteredNames = collection.chain() // start chain, returns wrapper around collection's models
.filter(function(item) { return item.get('age') > 10; }) // returns wrapped array excluding Tim
.map(function(item) { return item.get('name'); }) // returns wrapped array containing remaining names
.value(); // terminates the chain and returns the resulting array
console.log(filteredNames); // logs: ['Ida', 'Rob']
{ name: 'Tim', age: 5 },
{ name: 'Ida', age: 26 },
{ name: 'Rob', age: 55 }
]);
var filteredNames = collection.chain() // start chain, returns wrapper around collection's models
.filter(function(item) { return item.get('age') > 10; }) // returns wrapped array excluding Tim
.map(function(item) { return item.get('name'); }) // returns wrapped array containing remaining names
.value(); // terminates the chain and returns the resulting array
console.log(filteredNames); // logs: ['Ida', 'Rob']
RESTful Persistence
Saving models to the server
var TodosCollection = Backbone.Collection.extend({
model: Todo,
url: '/todos'
});
var todos = new TodosCollection();
todos.fetch();
var todo2 = todos.get(2);
todo2.set('title', 'fishing');
todo2.save(); // sends HTTP PUT to /todos/2
todos.create({title: 'Try out code samples'}); // sends HTTP POST to /todos and adds to collection
model: Todo,
url: '/todos'
});
var todos = new TodosCollection();
todos.fetch();
var todo2 = todos.get(2);
todo2.set('title', 'fishing');
todo2.save(); // sends HTTP PUT to /todos/2
todos.create({title: 'Try out code samples'}); // sends HTTP POST to /todos and adds to collection
A model’s validate() method is called automatically by save() and will trigger an invalid event on the model if validation fails.
Deleting models from the server
var todo2 = todos.get(2);
todo2.destroy(); // sends HTTP DELETE to /todos/2 and removes from collection
//Calling destroy on a Model will return false if the model isNew:
var todo = new Backbone.Model();
console.log(todo.destroy()); // false
todo2.destroy(); // sends HTTP DELETE to /todos/2 and removes from collection
//Calling destroy on a Model will return false if the model isNew:
var todo = new Backbone.Model();
console.log(todo.destroy()); // false
Routers
http://example.com/#about
http://example.com/#search/seasonal-horns/page2
var TodoRouter = Backbone.Router.extend({
/* define the route and function maps for this router */
routes: {
"about" : "showAbout",
/* Sample usage: http://example.com/#about */
"todo/:id" : "getTodo",
/* This is an example of using a ":param" variable which allows us to match
any of the components between two URL slashes */
/* Sample usage: http://example.com/#todo/5 */
"search/:query" : "searchTodos",
/* We can also define multiple routes that are bound to the same map function,
in this case searchTodos(). Note below how we're optionally passing in a
reference to a page number if one is supplied */
/* Sample usage: http://example.com/#search/job */
"search/:query/p:page" : "searchTodos",
/* As we can see, URLs may contain as many ":param"s as we wish */
/* Sample usage: http://example.com/#search/job/p1 */
"todos/:id/download/*documentPath" : "downloadDocument",
/* This is an example of using a *splat. Splats are able to match any number of
URL components and can be combined with ":param"s*/
/* Sample usage: http://example.com/#todos/5/download/files/Meeting_schedule.doc */
/* If you wish to use splats for anything beyond default routing, it's probably a good
idea to leave them at the end of a URL otherwise you may need to apply regular
expression parsing on your fragment */
"*other" : "defaultRoute", // http://example.com/# <anything>
"optional(/:item)": "optionalItem",
"named/optional/(y:z)": "namedOptionalItem"
/* Router URLs also support optional parts via parentheses, without having
to use a regex. */
},
showAbout: function(){
},
getTodo: function(id){
},
searchTodos: function(query, page){
},
downloadDocument: function(id, path){
},
defaultRoute: function(other){
console.log('Invalid. You attempted to reach:' + other);
}
});
new TodoRouter();
/* define the route and function maps for this router */
routes: {
"about" : "showAbout",
/* Sample usage: http://example.com/#about */
"todo/:id" : "getTodo",
/* This is an example of using a ":param" variable which allows us to match
any of the components between two URL slashes */
/* Sample usage: http://example.com/#todo/5 */
"search/:query" : "searchTodos",
/* We can also define multiple routes that are bound to the same map function,
in this case searchTodos(). Note below how we're optionally passing in a
reference to a page number if one is supplied */
/* Sample usage: http://example.com/#search/job */
"search/:query/p:page" : "searchTodos",
/* As we can see, URLs may contain as many ":param"s as we wish */
/* Sample usage: http://example.com/#search/job/p1 */
"todos/:id/download/*documentPath" : "downloadDocument",
/* This is an example of using a *splat. Splats are able to match any number of
URL components and can be combined with ":param"s*/
/* Sample usage: http://example.com/#todos/5/download/files/Meeting_schedule.doc */
/* If you wish to use splats for anything beyond default routing, it's probably a good
idea to leave them at the end of a URL otherwise you may need to apply regular
expression parsing on your fragment */
"*other" : "defaultRoute", // http://example.com/# <anything>
"optional(/:item)": "optionalItem",
"named/optional/(y:z)": "namedOptionalItem"
/* Router URLs also support optional parts via parentheses, without having
to use a regex. */
},
showAbout: function(){
},
getTodo: function(id){
},
searchTodos: function(query, page){
},
downloadDocument: function(id, path){
},
defaultRoute: function(other){
console.log('Invalid. You attempted to reach:' + other);
}
});
new TodoRouter();
Backbone.history - This will automatically handle routes that have been defined and trigger callbacks when they’ve been accessed.
var TodoRouter = Backbone.Router.extend({
/* define the route and function maps for this router */
routes: {
"about" : "showAbout",
"search/:query" : "searchTodos",
"search/:query/p:page" : "searchTodos"
},
showAbout: function(){},
searchTodos: function(query, page){
var page_number = page || 1;
console.log("Page number: " + page_number + " of the results for todos containing the word: " + query);
}
});
var myTodoRouter = new TodoRouter();
Backbone.history.start();
// http://localhost/#search/job/p3 logs: Page number: 3 of the results for todos containing the word: job
// http://localhost/#search/job logs: Page number: 1 of the results for todos containing the word: job
// etc.
/* define the route and function maps for this router */
routes: {
"about" : "showAbout",
"search/:query" : "searchTodos",
"search/:query/p:page" : "searchTodos"
},
showAbout: function(){},
searchTodos: function(query, page){
var page_number = page || 1;
console.log("Page number: " + page_number + " of the results for todos containing the word: " + query);
}
});
var myTodoRouter = new TodoRouter();
Backbone.history.start();
// http://localhost/#search/job/p3 logs: Page number: 3 of the results for todos containing the word: job
// http://localhost/#search/job logs: Page number: 1 of the results for todos containing the word: job
// etc.
Backbone’s Sync API
Backbone.emulateHTTP = false; // set to true if server cannot handle HTTP PUT or HTTP DELETE
Backbone.emulateJSON = false; // set to true if server cannot handle application/json requests
Backbone.sync
Backbone.sync = function(method, model, options) {
};
var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch': 'PATCH',
'delete': 'DELETE',
'read': 'GET'
};
};
var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch': 'PATCH',
'delete': 'DELETE',
'read': 'GET'
};
The sync method is called with three parameters:
method: One of create, update, patch, delete, or read
model: The Backbone model object
options: May include success and error methods
Implementing a new sync method can use the following pattern:
Backbone.sync = function(method, model, options) {
function success(result) {
// Handle successful results from MyAPI
if (options.success) {
options.success(result);
}
}
function error(result) {
// Handle error results from MyAPI
if (options.error) {
options.error(result);
}
}
options || (options = {});
switch (method) {
case 'create':
return MyAPI.create(model, success, error);
case 'update':
return MyAPI.update(model, success, error);
case 'patch':
return MyAPI.patch(model, success, error);
case 'delete':
return MyAPI.destroy(model, success, error);
case 'read':
if (model.cid) {
return MyAPI.find(model, success, error);
} else {
return MyAPI.findAll(model, success, error);
}
}
};
function success(result) {
// Handle successful results from MyAPI
if (options.success) {
options.success(result);
}
}
function error(result) {
// Handle error results from MyAPI
if (options.error) {
options.error(result);
}
}
options || (options = {});
switch (method) {
case 'create':
return MyAPI.create(model, success, error);
case 'update':
return MyAPI.update(model, success, error);
case 'patch':
return MyAPI.patch(model, success, error);
case 'delete':
return MyAPI.destroy(model, success, error);
case 'read':
if (model.cid) {
return MyAPI.find(model, success, error);
} else {
return MyAPI.findAll(model, success, error);
}
}
};
Nutritionix Health Tracker Project
Develop a single page app that tracks the user's calorie intake, and optionally, other health-related metrics. Typing food names into the search field will display a list of matching foods as provided by the health API. Users will be able to select an item from the list, and the item will be added to the list of foods the user is tracking. The total calorie count will also update to reflect the new daily total.
https://developer.nutritionix.com/docs/v1_1
Project Code
No comments:
Post a Comment