Backbone Router
by Joshua McNeese
HTML
<script src="https://cdn.jsdelivr.net/g/[email protected],[email protected],[email protected],[email protected],[email protected]"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css">
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<ul class="nav navbar-nav pull-left">
<li><a href="#posts"><span class="glyphicon glyphicon-list-alt"></span> Posts</a></li>
</ul>
<ul class="nav navbar-nav pull-right">
<li><a href="#posts/add"><span class="glyphicon glyphicon-plus-sign"></span> Add New</a></li>
</ul>
</div>
</nav>
<div id="content"></div>
<script id="post-template" type="text/x-handlebars-template">
<h1 class="title">{{title}} by {{author}}</h1>
<div class="body">
{{body}}
</div>
<a href="#posts/{{id}}/edit" title="Edit"><span class="glyphicon glyphicon-pencil"></span> Edit</a>
</script>
<script id="post-form-template" type="text/x-handlebars-template">
<input type="hidden" name="id" value="{{id}}" />
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" name="title" placeholder="Title" value="{{title}}" />
</div>
<div class="form-group">
<label for="body">Body</label>
<input type="textarea" class="form-control" name="body" placeholder="Body" value="{{body}}" />
</div>
<div class="form-group">
<label for="author">Author</label>
<input type="text" class="form-control" name="author" placeholder="Author" value="{{author}}" />
</div>
<button type="submit" class="btn btn-default">Submit</button>
</script>
CSS
body {
padding: 40px 0 0 10px;
}
JavaScript
var PostModel = Backbone.Model.extend({
defaults: {
id: '',
title: 'No title',
body: 'No body',
author: 'No author'
}
});
var PostView = Backbone.View.extend({
tagName: 'li',
className: 'post',
template: Handlebars.compile($('#post-template').html()),
initialize: function() {
this.listenTo(this.model, 'change', this.render);
this.render();
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
}
});
var PostsCollection = Backbone.Collection.extend({
model: PostModel
});
var PostsView = Backbone.View.extend({
tagName: 'ul',
className: 'posts',
initialize: function() {
this.listenTo(this.collection, 'update reset', this.render);
this.render();
},
render: function() {
var $el = this.$el;
this.collection.each(function(postModel) {
var postView = new PostView({
model: postModel
});
$el.append(postView.el);
});
}
});
var FormView = Backbone.View.extend({
tagName: 'form',
className: 'post-form',
template: Handlebars.compile($('#post-form-template').html()),
events: {
"submit": "onSubmit"
},
initialize: function() {
this.render();
},
render: function() {
this.$el.html(this.template(this.model ? this.model.toJSON() : {}));
},
setModel: function(model) {
this.model = model;
this.render();
},
onSubmit: function(e) {
e.preventDefault();
var data = {};
_.forEach(this.$el.serializeArray(), function(field) {
if (field.value) {
data[field.name] = field.value;
}
});
if (this.model && this.model.get('id')) {
this.model.set(data);
} else {
this.collection.create(data);
}
}
});
var PostsRouter = Backbone.Router.extend({
// the internal 'routes' parameter associates any hash keyword to a function
routes: {
"": "index",
"posts": "index",
"posts/add": "add",
"posts/:id/edit": "edit"
},
initialize: function() {
...