Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
647 views
in Technique[技术] by (71.8m points)

javascript - ko.computed property to determine visibility not working

In my KncokoutJS ViewModel, I have the follow computed property:

self.SelectedUserHasRoles = ko.computed(function () {
  if (self.isLoaded()) {
    return self.selectedUser().roles().length > 0;
  }
  return false;
});

And in my HTML, I have the following:

<!-- ko if: isLoaded() -->
  <!-- ko if: !SelectedUserHasRoles -->
  <div>
    <p>User has no Roles.</p>
  </div>
  <!-- /ko -->
  <!-- ko if: SelectedUserHasRoles -->
  <div class="roles-wrapper" data-bind="foreach: $root.selectedUser().roles()">
    <div class="role-token" data-bind="text: Name"></div>
  </div>
  <!-- /ko -->
<!-- /ko -->

In my code, I was to say this:

If data from AJAX call has finished loading (isLoaded is true), then for the currently selected user, check and see if he/she has any roles. If yes, then loop through them and show them, if not, show a bit of text saying 'User has no Roles.'

All seems to work, except for the showing User has no Roles text snippet. I've no idea why that isn't showing! I'm putting breakpoints into my computed property and can see that when I select a user with no roles, the expression (in console window) is false, and I'm negating that, so I should see that text snippet!

What am I doing wrong? I've created a screencast to make things easier to understand.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you want to negate an observable or computed value in a binding, you have to call it explicitly:

<!-- ko if: !SelectedUserHasRoles() -->

In the case of the if binding, there's also the ifnot counterpart:

<!-- ko ifnot: SelectedUserHasRoles -->

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
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...