8

What is the proper way to initialize a Knockout observableArray in a TypeScript class?

I am doing something like this:

   module ViewModel { 

        declare var ko;

        export class IndexPageViewModel {       

                agencies: any;                   

                constructor () {               
                    this.agencies = ko.observableArray([]);              
                }                                                                                                   
        }
    }


var ivm = new ViewModel.IndexPageViewModel();
ivm.agencies.push({name: "name", alias : "alias"});
for (var i = 0; i < ivm.agencies.length; i++){
    alert(ivm.agencies[i].name);
 }

Looks simple enough, but when I attempt to access the agencies property as indicated, execution hangs. Did I miss something?

Klaus Nji
  • 18,107
  • 29
  • 105
  • 185

2 Answers2

13

This line is where your mistake is:

agencies[i]

When you access an observable array, it is actually wrapped in a function so you do access it like:

agencies()[i]

Also make yourself a favor and download the Knockout definitions from: https://github.com/borisyankov/DefinitelyTyped

Then declare your attributes with types:

module ViewModel {

    export class IndexPageViewModel {

        agencies: KnockoutObservableArray;

        constructor () {
            this.agencies = ko.observableArray([]);
        }
    }
}
Boris Yankov
  • 1,530
  • 14
  • 21
  • That was it, thank you. Additional thanks for the link to all of the Typescript definitions. – Klaus Nji Nov 01 '12 at 12:03
  • Actually, accessing an observableArray is not entirely consistent. If you add items to the collection using this.agencies().push(anAgency), change notifications are not fired. But if you do this.agencies.push(anAgency), notifications are fired. – Klaus Nji Nov 01 '12 at 21:04
  • 2
    @KNji it is consistent. If you call a method on this.agencies you are accessing the KO wrapper around your array. Hence any changes will be noted and an event will be fired. If you invoke this.agencies() you resolve the observable and hence will get the underlying array as a result. Pushing objects directly on this array wil bypass the KO framework and thus no change event is fired. – thomaux Dec 17 '12 at 08:15
5

I just did this in TypeScript 1.3 (though it should work in older versions too):

pendingAddAssociations: KnockoutObservableArray<ControllerModel> = ko.observableArray<ControllerModel>([]);

for your example, if you have an Agency class.

export class IndexPageViewModel {

        agencies: KnockoutObservableArray<Agency>;

        constructor () {
            this.agencies = ko.observableArray<Agency>([]);
        }
    }

I've also found that you can cast to any this.agencies = <any>[]; This is useful if you are using the Knockout ES5 plugin.

AlignedDev
  • 8,102
  • 9
  • 56
  • 91