BLAZORLOVER
BLAZORLOVER

Reputation: 2011

Computed observable not firing despite observable changing

I have the following:

sidebarCardVm.showCreateButton = ko.computed(function () {
    return
        (sidebarItemType == "Test") ||
        (sidebarItemType == "Test2" && self.selectedItem() != null); // when selectedItem() changes, I expect this to fire.  It does not.
});

I expect a change of selectedItem to trigger this:

self.selectedItem = ko.computed(function () {
    var matchingCard = getSelectedCard("Item")
    if (matchingCard != null && matchingCard.selectedItem() != null)
        return matchingCard.selectedItem();
    return null;
});

But it does not. I see self.selectedItem update, but showCreateButton doesn't follow suit. Why is this?

Upvotes: 0

Views: 145

Answers (1)

user3297291
user3297291

Reputation: 23397

Computeds are very smart in determining their dependencies. For example:

const myObs = ko.observable("Hello world");
const returnEarly = ko.observable(true);

const myComp = ko.computed(
  () => returnEarly() || myObs()
);

console.log(myComp()); // true
console.log(myObs.getSubscriptionsCount()); // 0

returnEarly(false);
console.log(myComp()); // "Hello world"
console.log(myObs.getSubscriptionsCount()); // 1
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Because when exitEarly is still true the code never reaches the point where it calls myObs, no subscription is created. Only once it gets to the second part of the ||, we'll start triggering updates for new values of myObs.

Therefore, this piece of code:

(sidebarItemType == "Test") ||
(sidebarItemType == "Test" && self.selectedItem() != null);

by definition, can not create a subscription to selectedItem.

Whenever sideBarItemType === "Test", it will return early and not call selectedItem.

Upvotes: 2

Related Questions