Chetan
Chetan

Reputation: 1468

Backbone View Inheritance to GrandChild Level

I have three backbone views like this :

ParentView = Backbone.View.extend({
    addUsers : function()
    {
        console.log("Parent's Add User");
    },

    addProject : function()
    {
        console.log("Parent's Add Project");
    }
});

ChildView = ParentView.extend({
    addProject : function()
    {
        var self = this;

        console.log("Child's add Project");

        self.constructor.__super__.addProject.apply(self);
    }
});

GrandChildView = ChildView.extend({
    addItem : function()
    {
        var self = this;
        self.addProject();
    },

    addUsers : function()
    {
        var self = this;
        console.log("Grand Child's Add users");
        self.constructor.__super__.addUsers.apply(self);
    }
});

var vChild = new ChildView();
vChild.addProject(); // works fine, by calling it own and parent's functions.

var vGrandChild = new GrandChildView();
vGrandChild.addUsers();   // This throws Maximum call stack size exceeded error,

when I create new instance of GrandChildView and then call its addUsers method, it throws maximum stack size exceeded, I guess that is becuase it keeps calling itself. but not able to figure out. the reason seems to be calling super's method.

Thank you.

Upvotes: 0

Views: 614

Answers (3)

Alexander Günther
Alexander Günther

Reputation: 180

I took your code, converted to CoffeeScript and it gave me this JavaScript, which works for me:

var ChildView, GrandChildView, ParentView,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

ParentView = (function(_super) {

  __extends(ParentView, _super);

  ParentView.name = 'ParentView';

  function ParentView() {
    return ParentView.__super__.constructor.apply(this, arguments);
  }

  ParentView.prototype.addUsers = function() {
    return console.log("Parent's Add User");
  };

  ParentView.prototype.addProject = function() {
    return console.log("Parent's Add Project");
  };

  return ParentView;

})(Backbone.View);

ChildView = (function(_super) {

  __extends(ChildView, _super);

  ChildView.name = 'ChildView';

  function ChildView() {
    this.addProject = __bind(this.addProject, this);
    return ChildView.__super__.constructor.apply(this, arguments);
  }

  ChildView.prototype.addProject = function() {
    console.log("Child's add Project");
    return ChildView.__super__.addProject.apply(this, arguments);
  };

  return ChildView;

})(ParentView);

GrandChildView = (function(_super) {

  __extends(GrandChildView, _super);

  GrandChildView.name = 'GrandChildView';

  function GrandChildView() {
    this.addUsers = __bind(this.addUsers, this);

    this.addItem = __bind(this.addItem, this);
    return GrandChildView.__super__.constructor.apply(this, arguments);
  }

  GrandChildView.prototype.addItem = function() {
    return this.addProject();
  };

  GrandChildView.prototype.addUsers = function() {
    console.log("Grand Child's Add users");
    return GrandChildView.__super__.addUsers.apply(this, arguments);
  };

  return GrandChildView;

})(ChildView);

From my understanding the tricky point is you are binding this to self inside the functions. This which will happen each time you call the function with the context you are calling the function, which is exactly what you are trying to omit. You need to bind this in a function as you do it usually only for callback, or situations where you have no reference to the object you are calling the function on, just the reference to the function. So if you need to bind this for such situations do it outside the function.

Upvotes: 0

ggozad
ggozad

Reputation: 13105

What you are actually doing, which you should be able to understand if you actually follow the steps of your function calls is indeed calling in an infinite loop the "grand child" view :)

Hint: It's worth the exercise to think what this is every time as you apply....;)

Otherwise this is probably what you mean to achieve:

ParentView = Backbone.View.extend({
    addUsers : function()
    {
        console.log("Parent's Add User");
    },

    addProject : function()
    {
        console.log("Parent's Add Project");
    }
});

ChildView = ParentView.extend({
    addProject : function()
    {
        console.log("Child's add Project");

        ParentView.prototype.addProject.call(this);
    }
});

GrandChildView = ChildView.extend({

    addItem : function()
    {
        this.addProject();
    },

    addUsers : function()
    {
        console.log("Grand Child's Add users");
        ChildView.prototype.addUsers.call(this);
    }
});

var vChild = new ChildView();
vChild.addProject(); // works fine, by calling it own and parent's functions.

var vGrandChild = new GrandChildView();
vGrandChild.addUsers();   

Upvotes: 1

fguillen
fguillen

Reputation: 38888

Just for try: add this to your ChildView:

addUsers : function()
{
    var self = this;
    console.log("Child's Add users");
    self.constructor.__super__.addUsers.apply(self);
}

Maybe as the addUsers function is not properly defined in the ChildView.prototype but it is inherited then it is not found and is relaying in the self.prototype. I don't know.. as I say I don't think JS is meaning to work with inheritance this way as common OO oriented language.

Upvotes: 0

Related Questions