Nick Nick - 3 months ago 13
Javascript Question

Knockout computer function cannot be evaluated

Please check my plunkr here:

https://plnkr.co/edit/pwKohFTmLPW1BKNwHxWR?p=preview

I have a simple computer function:

self.SubscribersOrEmails = ko.computed(function() {
var counter = 0;
if (self.Emails != null && self.Subscribers != null) {
counter = self.Emails().length + self.Subscribers().length;
}
console.log("counter: " + counter);
return counter;
}, self);


When I get to use it like this:
self.SubscribersOrEmails()
then I get the error that
'SubscribersOrEmails is not a function'

but when I do
console.log(self.SubscribersOrEmails)
then it prints out a function. So it IS a function.
How do I use it then? I want it to return an integer. Currently it returns a function, but I am not allowed to evaluate it.

Any idea what is going on with it?

UPDATE



Some people have been seeing an old version of the plunkr for some bizarre reason.

I can now see that it's a declaration order issue.
If I do this:

self.SubscribersOrEmails = ko.computed(function() {
var counter = 0;
if (self.Emails != null && self.Subscribers != null) {
counter = self.Emails().length + self.Subscribers().length;
}
console.log("counter: " + counter);
return counter;
}, self);

self.Subscribers = ko.observableArray().extend({ required: { onlyIf: function () { console.log(self.SubscribersOrEmails()); return self.SubscribersOrEmails === 0}, params: 'Subscribers', message: "Please either select a user or type email address(es)" } })
self.Emails = ko.observableArray().extend({ required: { onlyIf: function () { return self.SubscribersOrEmails == 0 }, params: 'Emails' } })


Then the function works but Emails and Subscribers is always zero because they don't exist when they are read.

If I do the opposite then the function doesn't exist.

So all possible order declarations cause problems :(

Answer

This is because your order of declaration. In the extend method, you are referring to a method that hasn't been declared yet. You can fix this by extending those observables after declaring that computed property.

self.Subscribers = ko.observableArray();
self.Emails = ko.observableArray();
self.SubscribersOrEmails = ko.computed(function() {
    var counter = 0;
    if (self.Emails != null && self.Subscribers != null) {
        counter = self.Emails().length + self.Subscribers().length;
    }
    console.log("counter: " + counter);
    return counter;
}, self); 

self.Subscribers.extend({ required: { onlyIf: function () { return self.SubscribersOrEmails == 0 }, params: 'Subscribers', message: "Please either select a user or type email address(es)" } })
self.Emails.extend({ required: { onlyIf: function () { return self.SubscribersOrEmails == 0 }, params: 'Emails' } })
Comments