KO Computed Observables

by tomas_eklund

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<label>Dozen:</label><br>
<input type="number" data-bind="value: dozen">
<span class="error" data-bind="text: error"></span><br>
<label>Pieces:</label><br>
<input type="number" data-bind="value: pieces"><br>

CSS

body {
  background-color: #20262e;
  font-weight: bold;
  color: silver;
}

input {
  background-color: rgba(0, 0, 0, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.15);
  padding: 10px;
  color: white;
}

.error {
  color: red;
}

JavaScript

function ViewModel() {
  var self = this;
  self.error = ko.observable('');
  self.pieces = ko.observable('');
  self.dozen = ko.computed({
    read: function() {
      var p = parseInt(self.pieces(), 10);
      if (!p) return '';
      if (p % 12 === 0) return p / 12;
      else return '';
    },
    write: function(value) {
      if (/\D/.test(value)) {
        self.error('Only whole numbers');
        self.dozen.notifySubscribers();
      } else {
        self.error('');
        if (value) self.pieces(value * 12);
      }
    }
  });
}

ko.applyBindings(new ViewModel());