Knockout observableArray in TypeScript
Asked Answered
I

2

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?

Impurity answered 31/10, 2012 at 21:57 Comment(0)
G
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([]);
        }
    }
}
Godparent answered 31/10, 2012 at 22:42 Comment(3)
That was it, thank you. Additional thanks for the link to all of the Typescript definitions.Impurity
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.Impurity
@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.Necroscopy
P
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.

Putrid answered 31/12, 2014 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.