I'm writing my first Backbone blog app but when i try to add new post it throws an error.
Here is my app.js (all of backbone related components are in this file):
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
var Post = Backbone.Model.extend({});
var Posts = Backbone.Collection.extend({
model : Post,
url : "/posts"
});
var PostListView = Backbone.View.extend({
tagName: "li",
template: _.template("<a href='/posts/{{id}}'>{{title}}</a>"),
events: {
'click a': 'handleClick'
},
handleClick: function (e) {
e.preventDefault();
postRouter.navigate($(e.currentTarget).attr("href"),
{trigger: true});
},
render: function () {
this.el.innerHTML = this.template(this.model.toJSON());
return this;
}
});
var PostsListView = Backbone.View.extend({
template: _.template("<h1>My Blog</h1><a href='/post/new' class='newPost'>New</a> <ul></ul>"),
events: {
'click .newPost': 'handleNewClick'
},
handleNewClick: function (e) {
e.preventDefault();
postRouter.navigate($(e.currentTarget).attr("href"),
{trigger: true});
},
render: function () {
this.el.innerHTML = this.template();
var ul = this.$el.find("ul");
this.collection.forEach(function (post) {
ul.append(new PostListView({
model: post
}).render().el);
});
return this;
}
});
var PostView = Backbone.View.extend({
template: _.template($("#postView").html()),
events: {
'click a': 'handleClick'
},
render: function () {
var model = this.model.toJSON();
model.pubDate = new Date(Date.parse(model.pubDate)).toDateString();
this.el.innerHTML = this.template(model);
return this;
},
handleClick: function (e) {
e.preventDefault();
postRouter.navigate($(e.currentTarget).attr("href"),
{trigger: true});
return false;
}
});
var PostFormView = Backbone.View.extend({
tagName: 'form',
template: _.template($("#postFormView").html()),
initialize: function (options) {
this.posts = options.posts;
},
events: {
'click #submitPost': 'createPost',
'click .back' : 'backButton'
},
render: function () {
this.el.innerHTML = this.template();
return this;
},
backButton: function (e) {
e.preventDefault();
postRouter.navigate($(e.currentTarget).attr("href"),
{trigger: true});
return false;
},
createPost: function (e) {
e.preventDefault();
var postAttrs = {
content: $("#postText").val(),
title: $("#postTitle").val(),
pubDate: new Date(),
};
this.posts.create(postAttrs);
postRouter.navigate("/", { trigger: true });
return false;
}
});
var PostRouter = Backbone.Router.extend({
initialize: function (options) {
this.posts = options.posts;
this.main = options.main;
},
routes: {
'': 'index',
'posts/:id': 'singlePost',
'post/new': 'newPost'
},
index: function () {
var pv = new PostsListView({ collection: this.posts });
this.main.html(pv.render().el);
},
singlePost: function (id) {
var post = this.posts.get(id);
var pv = new PostView({ model: post });
this.main.html(pv.render().el);
},
newPost: function () {
var pfv = new PostFormView({ posts: this.posts });
this.main.html(pfv.render().el);
}
});
I also have some view templates in my index file :
<!DOCTYPE html>
<html>
<head>
<title> Simple Blog </title>
</head>
<body>
<div id="main"></div>
<script src="/jquery.js"></script>
<script src="/underscore.js"></script>
<script src="/backbone.js"></script>
<script type="text/template" id="postFormView">
<a href="/" class="back">All Posts</a><br />
<input type="text" id="postTitle" placeholder="post title" />
<br />
<textarea id="postText"></textarea>
<br />
<button id="submitPost"> Post </button>
</script>
<script type="text/template" id="postView">
<a href='/'>All Posts</a>
<h1>{{title}}</h1>
<p>{{pubDate}}</p>
{{content}}
</script>
<script src="/app.js"></script>
<script>
var postRouter = new PostRouter({
posts: new Posts(<%- posts %>),
main: $("#main")
});
Backbone.history.start({pushState: true});
</script>
</body>
</html>
Viewing posts and home page works fine but when I try to create a new post I get this error from the dev tools console:
Uncaught ReferenceError: id is not defined
at child.eval (eval at _.template (http://localhost:3000/underscore.js:1:1), <anonymous>:6:8)
at child.template (http://localhost:3000/underscore.js:1214:21)
at child.render (http://localhost:3000/app.js:27:34)
at http://localhost:3000/app.js:48:16
at Array.forEach (native)
at Function._.each._.forEach (http://localhost:3000/underscore.js:79:11)
at child.Collection.(anonymous function) [as forEach] (http://localhost:3000/backbone.js:956:24)
at child.render (http://localhost:3000/app.js:45:25)
at child.index (http://localhost:3000/app.js:118:27)
at Object.callback (http://localhost:3000/backbone.js:1242:30)
The server is a simple nodejs server and output for creating a post is something like this:
{"result":{"ok":1,"n":1},"ops":[{"content":"kljhlkjh","title":"jkhjklh","pubDate":"2016-10-29T10:21:47.793Z","id":12,"_id":"5814783b732bbe153461eca4"}],"insertedCount":1,"insertedId
s":["5814783b732bbe153461eca4"]}