Search code examples
knockout.jsknockout-es5-plugin

knockout-es5 boolean setter does not work properly


I'm trying to use a negated boolean setter with knockout-es5, however changes using the toggleViewModel function are not picked up in the view.

When I use self.showViewModelData(!self.showViewModelData()) it does work as expected. In the debugger I can see that the values are actually correctly set in the viewmodel which leads me to think for some reason setting properties like does not work correctly.

Anything I'm missing here?

var vm = (function(){
  var self = this;

  self.showViewModelData = ko.observable(false);

  self.toggleViewModel = function(){
    self.showViewModelData = !self.showViewModelData;
  }

  var vm = {
    toggleViewModel: self.toggleViewModel,
    showViewModelData: self.showViewModelData
  }

  ko.track(vm);
  return vm;
})();
ko.applyBindings(vm);

Solution

  • Your problem is that you are using the revealing module pattern incorrectly (you trying to hang everything on self which is used when using the constructor pattern (demo JSFiddle)):

    var vm = (function(){
      //this will be the global (window) object
      var self = this;
    
      self.showViewModelData = ko.observable(false);
    
      self.toggleViewModel = function(){
        //when exectued "self" will be the global (window) object 
        //but you have bound to vm so you are setting the wrong property here
        self.showViewModelData = !self.showViewModelData;
      }
    
      //this object gets bound by KO 
      var vm = {
        toggleViewModel: self.toggleViewModel,
        showViewModelData: self.showViewModelData
      }
    
      ko.track(vm);
      return vm;
    })();
    

    The correct usage is the following: instead of self you need to define your fields and functions locally with var:

    var vm = (function(){
    
      var showViewModelData = ko.observable(false);
    
      var toggleViewModel = function(){
          this.showViewModelData = !this.showViewModelData;
      }
    
      var vm = {
        toggleViewModel: toggleViewModel,
        showViewModelData: showViewModelData
      }
    
      ko.track(vm);
      return vm;
    })();
    

    Demo JSFiddle.

    But the whole point of using the Knockout-ES5 plugin is that you don't to explicitly declare observable properties: So you just to declare your showViewModelData as a regular property and it should also work fine