Visible binding in KnockoutJS does not work proper

2019-08-19 03:57发布

问题:

I have a drop down box including 'dog', 'cat', 'bear'. I want to show an input box in front of the select box when the user select 'cat' or 'dog'. So I am using the visible binding to do this:

<select data-bind="options:animals, value: animal"</select>
<input data-bind="value: description, visible: showDescription"/>
self.showDescription=ko.observable(false);

self.showOtherDescription = function() {
   if(animal == 'cat' || animal == 'dog'){
     self.showDescription=ko.observable(true);
   }
}

It is working when the page is loaded. But when I change the option to 'bear' from the drop down it does not hide the input box. Does anybody have any idea?

回答1:

The showDescription observable really should be the computed function to drive the visibility of the <input> element on the view:

self.showDescription = ko.computed(function(){
    return (animal() === 'cat' || animal() === 'dog');
});


回答2:

This is the way to go IMO:

var ViewModel = function() {
  var self = this;
  
  self.animals = ['', 'cat', 'dog', 'mouse', 'bird'];
  
  self.animal = ko.observable('');
  
  self.description = ko.observable('');

  self.showOtherDescription = ko.computed(function() {
    return self.animal() === 'cat' || self.animal() === 'dog';
  });
};

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<select data-bind="options: animals, value: animal"></select>
<input data-bind="value: description, visible: showOtherDescription"/>

It changes / adds a few things to your code:

  • The showDescription is not needed, at least not in the context of the things you've posted;
  • The showOtherDescription needs to be a computed so it's updated when dependencies are updated;
  • showOtherDescription should not have a "setter" function or side-effects that change other observables. If you do need such a setter, check out writeable computed observables;
  • If you use animal as a two-way bound property, it needs to be an observable and thus needs to be invoked as a function to get its value.
  • I'm not sure how the code you posted would work, as refer to animal like animal == 'cat' as well as use it in the View. I think it should probably be exposed publicly on the ViewModel, and as such you should refer to it as self.animal.


回答3:

I think you are assigning to the observable instead of using observable function invocation in the "showOtherDescription" function , try this

//self.showDescription=ko.observable(true);
self.showDescription(true);


标签: knockout.js