I'm putting together a simple todo list app based on some examples to learn about Backbone. I'm running the code on Django for database and using Tastypie to do the API, and am trying to use Backbone (with RequireJS for AMD) but am having trouble with the following error in my console:
Uncaught TypeError: Object function (){ return parent.apply(this, arguments); } has no method 'on'
I think my app is having trouble communicating via the backbone collection,because it seems to get this error at about here in my app.js (main app view):
// Bind relavent events to the todos.
this.listenTo(Todos, "add", this.addOne);
this.listenTo(Todos, "reset", this.addAll);
I've seen some similar issues on here but I'm just breaking into this stuff so an explanation of what's happening would be much appreciated.
collections.js
define([
'underscore',
'backbone',
'app/app',
'app/models/model'
], function(_, Backbone, app, Todo){
// The collection of our todo models.
TodoList = Backbone.Collection.extend({
model: Todo,
// A catcher for the meta object TastyPie will return.
meta: {},
// Set the (relative) url to the API for the item resource.
url: "/api/item",
// Our API will return an object with meta, then objects list.
parse: function(response) {
this.meta = response.meta;
return response.objects;
}
});
var Todos = new TodoList();
return Todos;
});
app.js:
define([
'jquery',
'underscore',
'backbone',
'app/models/model',
'app/collections/collection',
'app/views/view'
], function($, _, Backbone, Todos, Todo, TodoList, TodoView){
// The view for the entire app.
var AppView = Backbone.View.extend({
el: "#todo-app",
// Bind our events.
events: {
"keypress #new-todo": "createOnEnter",
},
initialize: function() {
// TastyPie requires us to use a ?format=json param, so we'll
// set that as a default.
$.ajaxPrefilter(function(options) {
_.extend(options, {format: "json"});
});
// Bind relavent events to the todos.
this.listenTo(Todos, "add", this.addOne);
this.listenTo(Todos, "reset", this.addAll);
// Cache some of our elements.
this.$input = this.$("#new-todo");
// Get our todos from the API!
Todos.fetch();
},
// Crate a new todo when the input has focus and enter key is hit.
createOnEnter: function(event) {
var keyCode = event.keyCode || event.which,
title = this.$input.val().trim();
// If we haven't hit enter, then continue.
if (keyCode != 13 || !title) return;
// Create a new todo.
Todos.create({title: title, complete: false});
// Reset the input.
this.$input.val("");
},
// Add a single todo to the list.
addOne: function(todo) {
var view = new TodoView({model: todo});
$("#todo-list").append(view.render().el);
},
// Clear the list and add each todo one by one.
addAll: function() {
this.$("todo-list").html("");
Todos.each(this.addOne, this);
}
});
return AppView;
});
The order of definitions and parameters in your app.js file is incorrect, you can try like this:
define([
'jquery',
'underscore',
'backbone',
'app/models/model',
'app/collections/collection',
'app/views/view'
], function($, _, Backbone, Todo, Todos, TodoView){