Jaydeep Patel
Jaydeep Patel

Reputation: 2423

Backbone change event is not firing

I am learning Backbone and struck at one place. I wanted to load model on page load. So I have below code.

<html>
<head>
    <script src="js/jquery.min.js"></script>
    <script src="js/underscore-min.js"></script>
    <script src="js/backbone-min.js"></script>
    <script src="js/json2.js"></script>
</head>
<body>
    <h1></h1>
    <div id="poview"></div>
    <script id="poTemplate" type="text/template">
        <td><%= Ponumber %></td>
        <td><%= Posuppliername %></td>
        <td><%= Postatusname %></td>
        <td><%= Podate %></td>
        <td><%= DispOrderTotal %></td>
    </script>
    <script type="text/javascript">
        (function($) {
            var PO = Backbone.Model.extend()

            var POList = Backbone.Collection.extend({
                url: 'po.json',
                model: PO,
                parse: function(response) {
                    console.log(response.PurchaseOrder)
                    return response.PurchaseOrder
                }
            })

            var POView = Backbone.View.extend({
                tagName: 'tr',
                template: $('#poTemplate').html(),
                initialize: function() {
                    _.bindAll(this, 'render')
                    this.model.bind('change', this.render)
                },
                events: {
                    'click': 'click'
                },
                render: function() {
                    console.log('po render')
                    var tmpl = _.template(this.template)
                    $(this.el).html(tmpl(this.model.toJSON()))
                    return this;
                },
                click: function() {
                    console.log('clicked....')
                }
            })

            var POListView = Backbone.View.extend({
                el: $('#poview'),
                initialize: function() {
                    _.bindAll(this, 'render', 'appendPO')
                    this.collection = new POList()
                    this.collection.bind('change', this.render, this)
                    this.collection.bind('add', this.render, this)
                    this.collection.fetch({add:true})
                },
                render: function() {
                    var self = this;
                    console.log(this.collection.models)
                    this.collection.each(function(po) {
                        self.appendPO(po)
                    }, this)
                },
                appendPO: function(po) {
                    var poView = new POView({
                        model: po
                    });
                    console.log(po)
                    $(this.el).append(poView.render().el)               
                }
            });

            var poListView = new POListView()

        })(jQuery)
    </script>
</body>
</html>

And below is json response from server

{
    "@totalCount": "1134",
    "PurchaseOrder": [
        {
            "ID": "689600",
            "Ponumber": "K037412201",
            "Poname": "",
            "Podate": "2011-12-26T10:03:24.000+05:30",
            "Posuppliername": "XYZ UPS Supplier",
            "Postatusname": "Approved - Supplier Received",
            "DispOrderTotal": "$1.99"
        },
        {
            "ID": "689601",
            "Ponumber": "K037412202",
            "Poname": "",
            "Podate": "2011-12-26T10:03:24.000+05:30",
            "Posuppliername": "ABC UPS Supplier",
            "Postatusname": "Approved - Supplier Received",
            "DispOrderTotal": "$1.99"
        }
    ]
}

But when the page is loaded render method on POListView is not fired. What is issue in this code?

Edit

jQuery(function($){
  ...
});

If I use above convention also, that does not work.

Working example Refer answer from @JayC

<html>
<head>
    <script src="js/jquery.min.js"></script>
    <script src="js/underscore.js"></script>
    <script src="js/backbone.js"></script>
    <script src="js/json2.js"></script>
</head>
<body>
    <h1></h1>
    <div id="poview"></div>
    <script id="poTemplate" type="text/template">
        <td><%= Ponumber %></td>
        <td><%= Posuppliername %></td>
        <td><%= Postatusname %></td>
        <td><%= Podate %></td>
        <td><%= DispOrderTotal %></td>
    </script>
    <script type="text/javascript">

        jQuery(function($) {
            var PO = Backbone.Model.extend({
                idAttribute: 'ID'
            })

            var POList = Backbone.Collection.extend({
                url: 'po.json',
                model: PO,
                parse: function(response) {
                    console.log('parse')
                    return response.PurchaseOrder
                }
            })

            var POView = Backbone.View.extend({
                tagName: 'tr',
                template: $('#poTemplate').html(),
                initialize: function() {
                    _.bindAll(this, 'render', 'click')
                },
                events: {
                    'click': 'click'
                },
                render: function() {
                    var tmpl = _.template(this.template)
                    $(this.el).html(tmpl(this.model.toJSON()))
                    return this;
                },
                click: function() {
                    console.log('clicked.... ' + this.model.id)
                }
            })

            var POListView = Backbone.View.extend({
                el: $('#poview'),
                initialize: function() {
                    _.bindAll(this, 'render', 'appendPO')
                    this.collection = new POList()
                    this.collection.bind('reset', this.render, this)
                    this.collection.fetch()
                },
                render: function() {
                    var self = this;
                    console.log(this.collection.models)
                    this.collection.each(function(po) {
                        self.appendPO(po)
                    }, this)
                },
                appendPO: function(po) {
                    var poView = new POView({
                        model: po
                    });
                    $(this.el).append(poView.render().el)               
                }
            });

            var poListView = new POListView()

        });
    </script>
</body>
</html>

Upvotes: 1

Views: 2914

Answers (2)

JayC
JayC

Reputation: 7141

I'm not seeing a binding to the reset event for your collection. The Backbone.js documentation now has a FAQ which explains events (finally!) and you can see from it that the reset event fires when the collection's entire contents have been replaced. On collections, that's what fetch normally does.

Upvotes: 5

biziclop
biziclop

Reputation: 14616

You wrote this, which executes the function immediately, when the DOM is not yet ready/available:

(function($){
  ...
})(jQuery);

But probably you wanted to write this (see http://api.jquery.com/jQuery/#jQuery3 ), which delays the function until the document is ready to be manipulated (attach your views, etc):

jQuery(function($){
  ...
});

Of course, only the actual initialization call should be wrapped into jQuery(), the other parts can remain in the plain closure.

Upvotes: 0

Related Questions