Chris
Chris

Reputation: 257

Backbone view that render child views of the same type causes endless loop

I have a category model that has child category models (That works fine) via this code:

var ImageSetCategory = Backbone.Model.extend({

        childrenCategories : new Array(),

        initialize: function () {
            var self = this;

            if (this.has('childrenCategories')) {

                $.each(this.get('childrenCategories'), function () {

                    var category = new ImageSetCategory(this);

                    self.childrenCategories.push(category);
                });
            }
        }
    });  

I also have a view that uses this model and renders all the children categories. (basicly, I'm attempting to make a tree view) It loops through the child categories using jquery, instantiates a new version of its self with each child category as the model, and renders it. But I'm hitting an endless loop that constantly is trying to process the same model.

var ImageSetCategoryView = Backbone.View.extend({

        tagName: 'li',

        className: 'nested-category',

        template: Handlebars.templates.imageSetCategoryView,

        render: function() {
            var self = this;

            var templateHtml = this.template(this.model.toJSON());

            self.$el.html(templateHtml);

            // *****************************
            // ENDLESS LOOP
            //   this is always the same model from the array
            // *****************************
            $.each(self.model.childrenCategories, function () {
                var categoryView = new ImageSetCategoryView({ model: this });

                self.$el.children('ul').append(categoryView.render().el);
            });

            return this;
        },
    });

Why is this causing an endless loop? Am I'm not following best practices? My background is C# so I'm trying to accomplish this in an OOP way.

Upvotes: 0

Views: 99

Answers (1)

zaquest
zaquest

Reputation: 2050

The reason is that all instances of ImageSetCategory share the same childrenCategories array. This way in ImageSetCategory.initialize function you create circular references (ImageSetCategory.childrenCategories points to the array and ImageSetCategory.childrenCategories[0] points to ImageSetCategory itself). This makes $.each in ImageSetCategoryView.render iterate over the same model. To avoid it you should initialize array inside of ImageSetCategory.initialize function:

var ImageSetCategory = Backbone.Model.extend({

    initialize: function () {
        var self = this;

        this.childrenCategories = [];

        if (this.has('childrenCategories')) {

            $.each(this.get('childrenCategories'), function () {

                var category = new ImageSetCategory(this);

                self.childrenCategories.push(category);
            });
        }
    }
});

To learn more about why this happens read about prototypes in JavaScript and how they are used to implement object-oriented paradigm.

Upvotes: 2

Related Questions