plrenaudin
plrenaudin

Reputation: 23

Backbone + RequireJS Object Inheritance

I have an issue using Backbone with RequireJS.

BaseListView.js

define(['backgrid',
  'backbone',
  'underscore', etc.], function (
    Backgrid,
    Backbone,
    _) {
  
  return Backbone.View.extend({
    initialize: function () {
      if(needDeleteCell) {
        this.addDeleteCell();
      }
      this.render();
    },

    addDeleteCell: function () {
      var ListViewDeleteCell = DeleteCell.extend({
        defaults: {
          successMsg: this.attributes.deleteSuccessMsg,
          failureMsg: this.attributes.deleteFailureMsg
        }
      });
      this.columns.push({
        name: "delete",
        label: "",
        editable: false,
        cell: ListViewDeleteCell
      }); 
    }
  });
});

ChildView.js

define(['i18next', './common/BaseListView'], function (i18n, BaseListView) {
  'use strict';

  return BaseListView.extend({
    columns: [{
      name: "_id",
      label: i18n.t('app.operationForm.id'),
      editable: false,
      cell: "string",
      renderable: false
    }, {
        name: "name",
        label: i18n.t('app.operationForm.nameLabel'),
        editable: false,
        cell: "string"
      }]
  });
});

Now if I want to use multiple instances of the child view, I have multiple "delete" columns (due to the columns.push() in the BaseListView) like if the columns attribute of the parent is a singleton instance.

In this case, ChildView is not the only Class extending the BaseListView

What is the proper way of doing this with Bacbkone + RequireJS?

Thank you.

Edit: this is the same issue as: Switching between singleton and prototype scope using RequireJS but I'd like to avoid the factory solution.

Upvotes: 2

Views: 60

Answers (2)

nikoshr
nikoshr

Reputation: 33344

Your ChildView.columns is an array and is shared among the instances. You could draw inspiration from the way Backbone handles default values hashes and

  1. define columns as a function in your ChildView
  2. have BaseListView shadow this definition by setting a columns attribute

For example,

var ChildView = BaseListView.extend({
    columns: function() { // define `columns` as a function
        return [{
            name: "_id",
            // ...
        }, {
            name: "name",
            // ...
         }];
    }
});

and

var BaseListView = Backbone.View.extend({
    initialize: function () {
        this.columns = _.result(this, 'columns');
        this.addDeleteCell();
    },

    addDeleteCell: function () {
        this.columns.push({
            name: "delete",
            // ...
        }); 
    }
});

And a demo http://jsfiddle.net/nikoshr/9fk8axpk/1/

Upvotes: 1

Tomasz Jakub Rup
Tomasz Jakub Rup

Reputation: 10680

In Your case ChildView.columns is prototype scope. Every instances has the same columns.

You may init columns in initialize function:

define(['i18next', './common/BaseListView'], function (i18n, BaseListView) {
  'use strict';

  return BaseListView.extend({
    initialize: function () {
      this.columns = [{
        name: "_id",
        label: i18n.t('app.operationForm.id'),
        editable: false,
        cell: "string",
        renderable: false
      }, {
        name: "name",
        label: i18n.t('app.operationForm.nameLabel'),
        editable: false,
        cell: "string"
      }];
      BaseListView.prototype.initialize.call(this);
    });
  }
});

Upvotes: 0

Related Questions