This files takes the images from the getting started section of backbonejs.org and combines them with TypeScript code examples that fit the tools and conventions used in cookiecutter-webapp-deluxe.
This image shows a five-step series of events.
- "Input" arrow: user clicks on a button.
- "Data" arrow: view sends updated data to the model.
- "Sync" arrow: model sends a request to the server and receives a response.
- "Change" broadcast: model updates itself and triggers the
change
event. - "Render" arrow: view responds to the
change
event by rendering itself.
These steps are highlighted in the example code below.
import { extend } from 'lodash';
import Model from '../core/model';
import View from '../core/view';
import bookTemplate from './bookDisplay-template';
// All Model subclasses implement step 4 out of the box.
class Book extends Model {}
class BookDisplay extends View {
initialize() {
// The next line ensures that step 5 always happens after 4.
this.listenTo(this.model, 'change', this.render);
}
render() {
// This is the implementation of step 5.
this.$el.html(this.template(this.model.toJSON()));
return this;
}
markRead() {
// The following line implements steps 2 and 3 and
// immediately triggers step 4.
this.model.save({read: true});
// We can delay step 4 until the server has confirmed the
// change by adding the second `options` argument like below.
this.model.save({read: true}, {wait: true});
}
}
extend(BookDisplay.prototype, {
template: bookTemplate,
events: {
// This line enables step 1: react to DOM events.
'click button': 'markRead',
},
});
let book = new Book({
title: 'Alice in Wonderland',
author: 'Lewis Carroll',
read: false,
});
let display = new BookDisplay({model: book});
// The next line also enables step 1: make display visible to user.
display.render().$el.appendTo('body');
Below, we illustrate a few phrases from the Models and Views section in the Backbone documentation with additional example code.
Model
- Loads and saves from the server.
// loads
book.fetch(...);
// saves
book.save(...);
// deletes
book.destroy(...);
- Emits events when data changes.
book.set(...);
book.unset(...);
book.clear();
// triggers 'change:title' if the title changed
// triggers 'change' if any attribute changed
// .set can also call this.validate(...) if you pass the {validate: true} option
book.fetch(...);
// triggers 'request' immediately
// calls this.set(...) if the request is successful, which may trigger 'change'
// triggers 'error' if the request fails
book.save(...);
// calls this.validate(...), which may trigger 'invalid' (and prevent the rest)
// triggers 'request' immediately
// calls this.set(...) immediately unless you pass {wait: true}
// triggers 'sync' if the request is successful
// calls this.set(...) after server confirmation if you pass {wait: true}
// triggers 'error' if the request fails
book.destroy(...);
// triggers 'request' immediately
// triggers 'destroy' if the request is successful
// triggers 'error' if the request fails
View
- Handles user input and interactivity.
class BookDisplay extends View {
// ...
markRead(event) {
this.model.save({read: true});
}
showNext(event) {
event.preventDefault();
this.trigger('next'); // let somebody else do the work
}
}
extend(BookDisplay.prototype, {
// ...
events: {
'click button': 'markRead',
'click a.next': 'showNext',
},
});
A Model manages an internal table of data attributes,
// The actual internal table. You shouldn't use this directly, but it
// can be useful during debugging.
book.attributes
// Safely get the value of a single attribute.
book.get('title');
// Or get it HTML-escaped.
book.escape('title');
// Check whether an attribute is set.
book.has('title');
// Safely set the value of a single attribute.
book.set('read', true);
// Safely set multiple values at once.
book.set({
title: 'Wuthering Heights',
author: 'Emily Brontë',
});
// Get a JSON-serializable copy of the attributes.
book.toJSON();
Work in progress.