Bruno
Bruno

Reputation: 4655

xxx is not a function in my ViewModel

why do I get a Uncaught TypeError: this.createRow is not a function on the matrixLengthsAvailable array construction ?

The createRow function is declared at the end of my viewmodel...

function TabBuyHarvesterModel() {
    self = this;

    this.selectedEmote = ko.observable('kappa');
    this.matrixLengthsAvailable = ko.observableArray([
        { length: 10, pctDetails: this.createRow(10) /*ko.mapping.fromJS({ rowLength: 10 })*/ }
        //30,
        //60,
        //180,
        //360,
        //720,
            //1440
        ]);

    this.selectEmote = function (emoteClicked) {
        self.selectedEmote(emoteClicked.emote);
    };

    this.createRow = function (rowLength) {
        var ret = new TabBuyHarvesterMatrixRowModel();
        ret.rowLength(rowLength);
        return ret;
    };
}

Upvotes: 0

Views: 933

Answers (4)

300 baud
300 baud

Reputation: 1672

If you only reference createRow from inside TabBuyHarvesterModel, then just making it a plain old function will work. Also, if you do this, then you will not have to define createRow before the matrixLengthsAvailable observable because JavaScript always hoists functions to the top of a closure even if they are not defined at the top of the closure:

function TabBuyHarvesterModel() {
    self = this;

    this.selectedEmote = ko.observable('kappa');
    this.matrixLengthsAvailable = ko.observableArray([
        { length: 10, pctDetails: createRow(10) /*ko.mapping.fromJS({ rowLength: 10 })*/ }
        //30,
        //60,
        //180,
        //360,
        //720,
            //1440
        ]);

    this.selectEmote = function (emoteClicked) {
        self.selectedEmote(emoteClicked.emote);
    };

    function createRow(rowLength) {
        var ret = new TabBuyHarvesterMatrixRowModel();
        ret.rowLength(rowLength);
        return ret;
    }
}

Upvotes: 1

CrimsonChris
CrimsonChris

Reputation: 4641

You're trying to use the createRow function before it's been created. Define createRow before matrixLengthsAvailable. A better approach would be to define createRow on the TabBuyHarvesterModel prototype. This defines the function a single time, before your class is ever instantiated.

function TabBuyHarvesterModel() {
    ...
}

TabBuyHarvesterModel.prototype.createRow = function (rowLength) {
    var ret = new TabBuyHarvesterMatrixRowModel();
    ret.rowLength(rowLength);
    return ret;
};

Upvotes: 1

Steen Tøttrup
Steen Tøttrup

Reputation: 3835

You should use self, as already pointed out, and use it right, as in everywhere, and then you need to switch the order of the methods, so that createRow is defined before it is needed.

Here: http://jsfiddle.net/oshmn46o/

function TabBuyHarvesterModel() {
var self = this;

self.createRow = function (rowLength) {
    var ret = new TabBuyHarvesterMatrixRowModel();
    ret.rowLength(rowLength);
    return ret;
};

self.selectedEmote = ko.observable('kappa');
self.matrixLengthsAvailable = ko.observableArray([
    { length: 10, pctDetails: self.createRow(10) /*ko.mapping.fromJS({ rowLength: 10 })*/ }
    //30,
    //60,
    //180,
    //360,
    //720,
        //1440
    ]);

self.selectEmote = function (emoteClicked) {
    self.selectedEmote(emoteClicked.emote);
};

}

Upvotes: 1

ryano.mcc13
ryano.mcc13

Reputation: 474

since ko.observableArray() is a function the this reference in this.createRow will reference the obervableArray context, change this to self.

Upvotes: 1

Related Questions