Search code examples
backbone.jsrequirejsmarionette

All Backbone models being initialized using RequireJS


I have a backbone/marionette project structured with requirejs.

define([
  'views/FormView',
  'path/to/Model',
], function (FormView, Model) {
  "use strict";

  return FormView.extend({

    model: new Model(),

    /* --- rest of view stuff --- */

  });
});

All the models in the project are being initialized (ie, initialize() will be called on all the models) when the page loads, but the views are only being initialized when they are instantiated by the controller.

The models should only be initalized once they are instantiated, and it's causing me a number of headaches.

Has anyone encountered this before?

Update:

thanks to Kevin and Yura for their answers, this code works:

define([
  'views/FormView',
  'path/to/Model',
], function (FormView, Model) {
  "use strict";

  return FormView.extend({

    model: undefined,

    initialize: function () {
      this.model = new Model();
    }

    /* --- rest of view stuff --- */

  });
});

Solution

  • Your problem is that

    model: new Model()
    

    runs as soon as this requirejs module is loaded into the browser. That is, when it is required, it returns the extended FormView, and that prototype is used for all instances of FormView.

    At this time new instance object of Model is instantiated and that same instance is used as the model property of every new instance of FormView.

    What you can do is instead of extending your FormView with the model property directly, delegate that model instance creation to initialization of the FormView instance:

    define([
     'views/FormView',
     'path/to/Model', 
    ], function (FormView, Model) {   "use strict";
    
      return FormView.extend({
    
        initialize: function(){
          /* Create property `model` whenever new instance of FormView is created */
          this.model = new Model();
        }
    
        /* --- rest of view stuff --- */
    
      });
    });
    

    Here's complete working example to show the difference:

    /** EXAMPLE 1 **
      Directly extending with `model` property and assigning 
      new instance of `Model`. Later you find out same model 
      instance is used for all `MyView` instances.
    */
    var MyView = Backbone.View.extend({
      model: new Backbone.Model(),
      render: function(){
        this.$el.text('I am ' + this.model.get('name'));
      }
    });
    
    var myView1 = new MyView();
    myView1.$el.appendTo(document.body);
    var myView2 = new MyView();
    myView2.$el.appendTo(document.body);
    
    myView1.model.set({name: "Joe"});
    myView2.model.set({name: "Bob"});
    
    myView1.render();
    myView2.render();
    
    /** EXAMPLE 2 **
      Extending with `model` in initialize will create and assign
      new instance of `model` every time `MyOtherView` instance is created.
    */
    var MyOtherView = Backbone.View.extend({
      initialize: function(){
        this.model = new Backbone.Model();
      },
      render: function(){
        this.$el.text('I am ' + this.model.get('name'));
      }
    });
    
    var myView1 = new MyOtherView();
    myView1.$el.appendTo(document.body);
    var myView2 = new MyOtherView();
    myView2.$el.appendTo(document.body);
    
    myView1.model.set({name: "Alice"});
    myView2.model.set({name: "Catrine"});
    
    myView1.render();
    myView2.render();
    <script src='http://code.jquery.com/jquery.js'></script>
    <script src='http://underscorejs.org/underscore.js'></script>
    <script src='http://backbonejs.org/backbone.js'></script>