In my KncokoutJS ViewModel, I have the follow computed property:
self.SelectedUserHasRoles = ko.computed(function () {
if (self.isLoaded()) {
return self.s
When you want to negate an observable or computed value in a binding, you have to call it explicitly:
In the case of the if
binding, there's also the ifnot
counterpart:
I think it's useful to understand why this is needed, since I see it happening a lot.
You could see the data-bind attribute as a comma separated string of key value pairs. Knockout wraps each of the values in a function, which it calls the valueAccessor
.
Essentially, you'll go from:
data-bind="if: SelectedUserHasRoles"
to
{
"if": function() { return SelectedUserHasRoles }
}
SelectedUserHasRoles
is an observable instance, which evaluates as truthy. When you negate this value using an !
, it will always be false
.
var myObs = ko.observable("anything");
var valueAccessor = function() { return myObs; };
var valueAccessorNeg = function() { return !myObs; };
console.log(valueAccessor()); // Returns the observable
console.log(valueAccessorNeg()); // Always prints false
The valueAccessor function is passed to the init
method of a binding. Usually, it is retrieved by calling it, and then unwrapped. Because the unwrap
utility doesn't care about whether you pass it an observable
or a plain value, you'll not see any errors when you make this mistake.
var myObs = ko.observable(false);
var va1 = function() { return myObs; };
var va2 = function() { return !myObs; };
var va3 = function() { return !myObs(); };
console.log(ko.unwrap(va1())); // false
console.log(ko.unwrap(va2())); // always false
console.log(ko.unwrap(va3())); // true
I hope this small peek under the hood might help you (and others that have made this mistake) to be able to determine when the ()
are needed in the future.