javascript - Backbone js - Uncaught type error: Cannot read property 'on' of undefined - Stack Overflow

I have the following a very simple ToDo List app using Backbone framework.<!doctype html><htm

I have the following a very simple ToDo List app using Backbone framework.

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>To do List</title>
    <style>
        pleted{
            text-decoration: line-through;
            color: #666;
        }
    </style>
    <script type="text/javascript" src=".11.1.js"></script>
    <script type="text/javascript" src="js/underscore.js"></script>
    <script type="text/javascript" src="js/backbone.js"></script>
</head>
<body>

    <h1>My Todos</h1>
    <div id="tasks">

        <button class="add">Add Task</button>
        <button class="clear hide">Clear All</button>
        <ul></ul>           

    </div>

    <script id="taskTemplate" type="text/template">
        <span class="<%= pleted ? 'pleted' : 'inplete' %>"><%= text %></span>
        <button class="plete"></button>
        <button class="delete"></button>
    </script>


    <script type="text/javascript">

        var Task = Backbone.Model.extend({
            defaults: {text: 'New task', pleted: false}

        });

        var Tasks = Backbone.Collection.extend({
            model: Task,
            el: '#tasks',
            initialize: function(){
                this.collection = new Tasks;
                this.collection.on('add', this.appendNewTask, this);

                this.items = this.$el.children('ul');
            },

            add: function(){
                var text = prompt('What do you need to do?');
                var task = new Task({text: text});
                this.collection.add(task);
            },

            appendNewTask: function(task){
                var TasksView = new TasksView({model:task});
                this.items.append(TasksView.el);
            },

            pleted: function(){
                return _.filter(this.models, function(model){
                    return model.get('pleted');
                });
            }
        });

        var TasksView = Backbone.View.extend({
            tagName: 'li',
            el: '#tasks',
            template: _.template($('#taskTemplate').html()),

            initialize: function(){

                this.model.on('change', this.render, this);
                this.model.on('remove', this.unrender, this);
                this.render();
            },

            render: function(){
                var markup = this.template(this.model.toJSON());
                    this.$el.html(markup);
            },

            unrender: function(){
                this.$el.remove();
            },

            events: { 
                'click .add': 'add',
                'click .clear': 'clearCompleted',
                'click .delete': 'delete',
                'click plete': 'updateStatus',
                'dblclick span': 'edit'
            },

            add: function(){
                    var text = prompt('What do you need to do?');
                    var task = new Task({text: text});
            },

            delete: function(){
                this.model.destroy();
                this.$el.remove();
            },

            updateStatus: function(){
                this.model.set('pleted', !this.model.get('pleted'));
            },

            edit: function(){
                var text = prompt('What should we change your task to?', this.model.get('text'))
                this.model.set('text',text);
            },

            clearCompleted: function(){
                var pletedTasks = this.collectionpleted();
                this.collection.remove(pletedTasks);
            }

        });     

        new TasksView;

    </script>


    <!-- Template JS -->


</body>
</html>

When I visit and load the page, and I could see an uncaught javascript error in the console log.

Uncaught TypeError: Cannot read property 'on' of undefined on line 78.

Looking through the code at the indictaed line number, it pointed to this

var TasksView = Backbone.View.extend({
    //.....
    initialize: function(){

        this.model.on('change', this.render, this); // this is the line the console is plaining
        this.model.on('remove', this.unrender, this);
        this.render();
    },
    //.....
});

After staring this for the next couple of hours and analysed the code, I couldn't figure out why this model needs to be instantiated when no tasks have been added to the TaskView Objects yet. It should be initialized as soon as I add or remove a new Task item into the model. I don't quite understand how this would throw an exception.

BTW, I'm a very new to Backbone.js and Underscore.js. I'm just following an online tutorial to figure out how these frameworks work...

Thanks.

I have the following a very simple ToDo List app using Backbone framework.

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>To do List</title>
    <style>
        .pleted{
            text-decoration: line-through;
            color: #666;
        }
    </style>
    <script type="text/javascript" src="http://code.jquery./jquery-1.11.1.js"></script>
    <script type="text/javascript" src="js/underscore.js"></script>
    <script type="text/javascript" src="js/backbone.js"></script>
</head>
<body>

    <h1>My Todos</h1>
    <div id="tasks">

        <button class="add">Add Task</button>
        <button class="clear hide">Clear All</button>
        <ul></ul>           

    </div>

    <script id="taskTemplate" type="text/template">
        <span class="<%= pleted ? 'pleted' : 'inplete' %>"><%= text %></span>
        <button class="plete"></button>
        <button class="delete"></button>
    </script>


    <script type="text/javascript">

        var Task = Backbone.Model.extend({
            defaults: {text: 'New task', pleted: false}

        });

        var Tasks = Backbone.Collection.extend({
            model: Task,
            el: '#tasks',
            initialize: function(){
                this.collection = new Tasks;
                this.collection.on('add', this.appendNewTask, this);

                this.items = this.$el.children('ul');
            },

            add: function(){
                var text = prompt('What do you need to do?');
                var task = new Task({text: text});
                this.collection.add(task);
            },

            appendNewTask: function(task){
                var TasksView = new TasksView({model:task});
                this.items.append(TasksView.el);
            },

            pleted: function(){
                return _.filter(this.models, function(model){
                    return model.get('pleted');
                });
            }
        });

        var TasksView = Backbone.View.extend({
            tagName: 'li',
            el: '#tasks',
            template: _.template($('#taskTemplate').html()),

            initialize: function(){

                this.model.on('change', this.render, this);
                this.model.on('remove', this.unrender, this);
                this.render();
            },

            render: function(){
                var markup = this.template(this.model.toJSON());
                    this.$el.html(markup);
            },

            unrender: function(){
                this.$el.remove();
            },

            events: { 
                'click .add': 'add',
                'click .clear': 'clearCompleted',
                'click .delete': 'delete',
                'click .plete': 'updateStatus',
                'dblclick span': 'edit'
            },

            add: function(){
                    var text = prompt('What do you need to do?');
                    var task = new Task({text: text});
            },

            delete: function(){
                this.model.destroy();
                this.$el.remove();
            },

            updateStatus: function(){
                this.model.set('pleted', !this.model.get('pleted'));
            },

            edit: function(){
                var text = prompt('What should we change your task to?', this.model.get('text'))
                this.model.set('text',text);
            },

            clearCompleted: function(){
                var pletedTasks = this.collection.pleted();
                this.collection.remove(pletedTasks);
            }

        });     

        new TasksView;

    </script>


    <!-- Template JS -->


</body>
</html>

When I visit and load the page, and I could see an uncaught javascript error in the console log.

Uncaught TypeError: Cannot read property 'on' of undefined on line 78.

Looking through the code at the indictaed line number, it pointed to this

var TasksView = Backbone.View.extend({
    //.....
    initialize: function(){

        this.model.on('change', this.render, this); // this is the line the console is plaining
        this.model.on('remove', this.unrender, this);
        this.render();
    },
    //.....
});

After staring this for the next couple of hours and analysed the code, I couldn't figure out why this model needs to be instantiated when no tasks have been added to the TaskView Objects yet. It should be initialized as soon as I add or remove a new Task item into the model. I don't quite understand how this would throw an exception.

BTW, I'm a very new to Backbone.js and Underscore.js. I'm just following an online tutorial to figure out how these frameworks work...

Thanks.

Share Improve this question asked May 23, 2014 at 7:42 awongCMawongCM 9275 gold badges22 silver badges47 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 0

You are not binding any model to your view. You can pass a model and/or collection when instantiating your new view. These properties will automatically be bound to this.model / this.collection of your view.

You are not passing a model so this.model is undefined in your view. You should pass the empty taskslist so that when it's populated later, the onchange will be triggered and your view will rerender.

new TasksView({model: new Tasks()});

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745622869a4636627.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信