1

I've started using Knockout JS and I applied a textarea counter to my viewmodel. But for some reason I get the error message:

TypeError: self.description(...) is undefined
var counter = self.description().length;

Even my teset fiddle doesn't work.

My code is this:

//HTML
<textarea data-bind="value: description, valueUpdate: 'afterkeydown'"></textarea>

//JS
jQuery(document).ready(function($) {
    ko.applyBindings(specialOfferPreviewModel());
});

function specialOfferPreviewModel() {

// -- This part works
    var self = this;
    self.promoTitle = ko.observable();
    self.description = ko.observable();
    self.fromDate = ko.observable();
    self.toDate = ko.observable();

    // To and from date
    self.validPeriod = ko.computed(function() {
        return self.fromDate + " - " + self.toDate;
    }, self);


// -- And this part breaks it
    self.count = ko.computed(function(){
        var counter = self.description().length;
        return counter;
    });
}

What am I missing? Any help appreciated!

Update:

I'm not sure the difference of these two, but either works:

//1
function specialOfferPreviewModel(){}
ko.applyBindings(specialOfferPreviewModel());

//2
var specialOfferPreviewModel = function(){}
var vm = new specialOfferPreviewModel ();
ko.applyBindings(vm);

They both work

Steven
  • 19,224
  • 47
  • 152
  • 257
  • Are you supposed to be executing the function here *before* passing it to `ko.applyBindings`? `ko.applyBindings(specialOfferPreviewModel());` – Kevin B May 30 '14 at 21:33
  • Not sure what you mean. I only know two ways of binding - see my updated question. – Steven May 30 '14 at 21:42
  • The reason i ask is because the function doesn't return anything, therefore, you're essentially doing `ko.applyBindings(undefined)` But i've never used ko, so i'm not sure exactly how it's intended to be used. – Kevin B May 30 '14 at 21:45
  • Additionally, `self` is `window`. Is that intended too? seems kindof odd to me to be adding a description property to the window. – Kevin B May 30 '14 at 21:49
  • ok. I think that's the way ko works. The other stuff in my view Model works fine. – Steven May 30 '14 at 21:50
  • See http://stackoverflow.com/questions/15956898/in-knockout-js-why-this-is-being-assigned-to-self regarding `self` :) – Steven May 30 '14 at 21:50
  • Right, but in this particular case, `this` is window, therefore `self` is window. (referring to your fiddle) – Kevin B May 30 '14 at 21:51

1 Answers1

1

Because the observable contains undefined as it hasn't been set.

By writing that :

self.description = ko.observable();

The observable contains undefined and you can see it if you decompose the code as follow :

self.description = ko.observable();
var content = self.description();
content.length;

In the fiddle :

var counter = self.description().length;

Is evaluated before it has been bound to the field, that's why its inner value is undefined.

So you can either initialize the observable :

self.description = ko.observable('');

Or you can defer the evaluation of the computed :

self.count = ko.computed({
    read: function () {
         var counter = self.description().length;
         return counter;
    },
    deferEvaluation: true
});

See doc

Damien
  • 8,889
  • 3
  • 32
  • 40