http://stackoverflow.com/questions/43453348/knockout-js-custom-binding-update-function-is-not-called#

by jlspake

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div data-bind="readonlyStarRating: myValue">
</div>

<input type="button" data-bind="click: dec" value="dec"/> 
<input type="button" data-bind="click: inc" value="inc"/>

CSS

.readonlyStarRating {
}

.chosen::after {
  content: '☆'
}

JavaScript

var viewModel = function() {
  var self = this;
  this.myValue = ko.observable(3);
  
  this.inc = function(){
  	this.myValue(this.myValue() + 1);    
  }
  this.dec = function(){
  	this.myValue(this.myValue() - 1);
  }
}

ko.bindingHandlers.readonlyStarRating = {
  init: function(element, valueAccessor) {
    $(element).addClass("readonlyStarRating");
    for (var i = 0; i < 5; i++)
      $("<span>").appendTo(element);
      
    $("span", element).each(function(index) {
      var observable = valueAccessor();
      $(this).hover(
        function() {
          $(this).prevAll().add(this).addClass("hoverChosen")
        },
        function() {
          $(this).prevAll().add(this).removeClass("hoverChosen")
        }
      )
    });
  },
  update: function(element, valueAccessor) {
    var observable = valueAccessor();
    $("span", element).each(function(index) {
      $(this).toggleClass("chosen", index < observable());
    });
  }
}

ko.applyBindings(new viewModel());