Backbone

Posted by alan on 2017-03-19

“Backbone JS”

Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.

Backbone

Image of Backbone

Models

Creating Models

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Song = Backbone.Model.extend({
idAttribute: 'songId',
urlRoot: '/api/songs',
defaults: {
downloads: 0
},
validate: function(attrs){
if (!attrs.title)
return 'Title is required.';
}
});
var song = new Song({ songId: 1, title: 'Blue in Green' });

Working with Attributes

1
2
3
4
5
song.set('genre', 'Jazz');
var genre = song.get('genre');
song.unset('genre');
var hasGenre = song.has('genre');
song.clear();

Validation

1
2
var isValid = song.isValid();
var lastError = song.validationError;

Syncing with the Server

1
2
3
4
5
6
7
8
9
10
11
12
song.fetch({
success: function(){…}
error: function(){…}
});
song.save({}, {
success: function(){…}
error: function(){…}
});
song.destroy({
success: function(){…}
error: function(){…}
});

Collections

Creating Collections

1
2
3
4
5
6
7
8
9
var Songs = Backbone.Collection.extend({
model: Song,
url: '/api/songs'
});
var songs = new Songs([
new Song({ title: 'Song 1' }),
new Song({ title: 'Song 2' })
]);

Working with Collections

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
songs.add(new Song({…});
var firstSong = songs.at(0);
var songWithIdC1 = songs.get('c1');
songs.remove(firstSong);
songs.push(new Song({…});
var lastSong = songs.pop();
var jazzSongs = songs.where({ genre: 'Jazz' });
var firstJazzSong = songs.findWhere({ genre: 'Jazz' });
var popularSongs = songs.filter(function(song){
return song.get('downloads') > 10;
});
songs.each(function(song){…});

Views

Creating Views

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var SongView = Backbone.View.extend({
tagName: 'span',
className: 'song',
id: '1234',
attributes: {
'data-genre': 'Jazz'
},
render: function() {
this.$el.html(…);
return this;
}
});
var songView = new SongView();
$('#container').html(songView.render().$el);

Passing Data to Views

1
2
3
4
5
6
7
8
9
var song = new Song({…});
var songView = new SongView({ model: song });
var SongView = Backbone.View.extend({
render: function() {
this.$el.html(this.model.get('title'));
return this;
}
});

Handling DOM Events

1
2
3
4
5
6
7
8
9
10
var SongView = Backbone.View.extend({
events: {
'click .bookmark': 'onClickBookmark'
},
onClickBookmark: function(e){
var $targetElement = $(e.target);
//…
}
});

Handling Model events

1
2
3
4
5
var SongView = Backbone.View.extend({
initialize: function(){
this.model.on('change', this.render, this);
}
});

Handling Collection Events

1
2
3
4
5
6
7
8
var SongView = Backbone.View.extend({
initialize: function(){
this.model.on('add', this.add, this);
}
add: function(model) {
//…
}
});

Templating

1
2
3
4
5
6
7
8
var SongView = Backbone.View.extend({
render: function(){
var source = $('#songTemplate').html();
var template = _.template(source);
this.$el.html(template(this.model.toJSON());
return this;
}
});
1
2
3
4
5
6
<script type=“text/html” id=“songTemplate”>
<%= title %>
<% if (downloads > 1000) { %>
Popular
<% } %>
</script>

Events

Binding and Triggering Custom Events

1
2
3
4
5
6
7
8
9
10
11
12
13
var person = {
walk: function(){
this.trigger('walking', { speed: 10 });
}
};
_.extend(person, Backbone.Events);
person.on('walking', function(e) {
console.log(e.speed);
});
person.off('walking');

Routers

Creating Routers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var AppRouter = Backbone.Router.extend({
routes: {
'albums': 'showAlbum'
},
showAlbum: function(){
// Usually get a model or collection from the server,
// pass it to the view and then render the view.
}
});
var router = new AppRouter();
// Tell Backbone to start monitoring address changes
Back.history.start();

Route Patterns

1
2
3
4
5
6
7
8
9
10
// Normal route
//
// albums
var AppRouter = Backbone.Router.extend({
routes: {
'albums': 'showAlbum'
},
showAlbum: function(){
}
});
1
2
3
4
5
6
7
8
9
10
// Route with parameters
//
// albums/1/songs/2
var AppRouter = Backbone.Router.extend({
routes: {
'albums/:albumId/songs/:songId': 'showSong'
},
showSong: function(albumId, songId){
}
});
1
2
3
4
5
6
7
8
9
10
// Route with a splat
//
// download/folderA/folderB/fileC
var AppRouter = Backbone.Router.extend({
routes: {
'download/*url': 'download'
},
download: function(url){
}
});
1
router.navigate(url, { trigger: true });