Search code examples
javascripttypescriptbackbone.jsrequirejs

Why does my backbone.Collection have only one element? (using Require, TypeScript, Jasmine)


I'm new to TypeScript and Jasmine, and still fairly new to Backbone and Require so I'm still trying to glue some pieces together.

In a Jasmine test in a TypeScript file, I am trying to define a backbone.Collection. Here is my code (stilghtly refactored)

(...)

class ModelA extends backbone.Model {
    idAttribute: "N";
    constructor(N: number, StringPropertyA: string, StringPropertyB: string, NumericPropertyA: number, NumericPropertyB: number, DatePropertyA: Date, DatePropertyB : Date) {
        super();
        this.attributes.N = N;
        this.attributes.StringPropertyA = StringPropertyA;
        this.attributes.StringPropertyB = StringPropertyB;
        this.attributes.NumericPropertyA = NumericPropertyA;
        this.attributes.NumericPropertyB = NumericPropertyB;
        this.attributes.DatePropertyA = DatePropertyA;
        this.attributes.DatePropertyB = DatePropertyB;
    }
}
            //var OldModelA = backbone.Model.extend({
            //    idAttribute: "N",
            //    constructor: function (N, PropertyA, PropertyB) {
            //        this.N = N;
            //        this.PropertyA = PropertyA;
            //        this.PropertyB = PropertyB;
            //    }
            //});

            var ModelACollection = backbone.Collection.extend({model: ModelA});

            var i = 1;
            var model1 = new ModelA(i++, "Abc", "dfD9"),
                model2 = new ModelA(i++, "Cde", "gdkl"),
                model3 = new ModelA(i++, "Cdy", "grger"),
                model4 = new ModelA(i++, "Zly", "dzeersds"),
                model5 = new ModelA(i++, "Zlz", "sdfsfz");

            var modelArray = [model1, model2, model3, model4, model5];

            var collection1 = new ModelACollection({ models: modelArray });
            var collection2 = new backbone.Collection({ models: modelArray });

(...)

I expected collection1.models and collection2.models to be arrays of 5 elements, but here are their content according to Chrome:

I guess I'm missing something...

Content of collection1 and collection2 according to Chrome's debugger

Further searching Similar result with

        var collection3 = new backbone.Collection();
        collection3.add(model1);
        collection3.add(model2);
        collection3.add(model3);
        collection3.add(model4);
        collection3.add(model5);

Solution

  • Your model definition is the culprit, it hopelessly confuses Backbone:

    • it misses a call to the parent constructor to inherit Backbone.Model properties. See the second example in http://backbonejs.org/#Model-constructor
    • if you want to write the attributes directly, they must be stored in the attributes hash, for example

      this.attributes.N = N;
      this.attributes.PropertyA = PropertyA;
      this.attributes.PropertyB = PropertyB;
      

    Given those points, a possible definition for ModelA, calling the parent constructor with a hash of attributes :

    var ModelA = Backbone.Model.extend({
        idAttribute: "N",
        constructor: function (N, PropertyA, PropertyB) {
            Backbone.Model.call(this, {
                N: N,
                PropertyA: PropertyA,
                PropertyB: PropertyB
            });
        }
    });
    
    var m = new ModelA(1, "Abc", "dfD9");
    console.log(m.toJSON());
    

    Note that you would create your collection with the array of models as first argument if you haven't overridden the constructor:

    var collection1 = new ModelACollection(modelArray);
    

    And a demo

    var ModelA = Backbone.Model.extend({
        idAttribute: "N",
        constructor: function (N, PropertyA, PropertyB) {
            Backbone.Model.call(this, {
                N: N,
                PropertyA: PropertyA,
                PropertyB: PropertyB
            });
        }
    });
    
    var i = 1;
    var model1 = new ModelA(i++, "Abc", "dfD9"),
        model2 = new ModelA(i++, "Cde", "gdkl"),
        model3 = new ModelA(i++, "Cdy", "grger"),
        model4 = new ModelA(i++, "Zly", "dzeersds"),
        model5 = new ModelA(i++, "Zlz", "sdfsfz");
    var collection1 = new Backbone.Collection([model1, model2, model3, model4, model5]);
    console.log(collection1.toJSON());
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.3/backbone-min.js"></script>