JSFiddle - React, Tailwind, and code Playground

by Fabian Wulf

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
    <div data-bind="component:{name:'available-items',params:vm}"></div>
    <ul data-bind="foreach: items">
      <li><span data-bind="text: location"></span> - <span data-bind="text: type"></span></li>
    </ul>
    <pre data-bind="text: ko.toJSON(vm.types, null, 2)"></pre>

CSS

pre {
  position: absolute;
  width: 300px;
  right: 0;
  top: 0;
}

JavaScript

ko.components.register("available-items", {
  viewModel: function(params) {
    function AvailableItems(params) {
      var self = this;
      self.params = params;
      self.location = "A";
      self.types = ko.computed(function() {
        var types = self.params.types();
        return ko.utils.arrayFilter(types, function(item) {
          return item.location == self.location;
        });
      });
      self.addItem = function(data, event) {
        self.params.items.addItem(self.location, data.type);
      };
    }
    return new AvailableItems(params);
  },
  template: '<div>' +
    '<h4>Add item</h4>' +
    '<ul data-bind="foreach: $root.types">' +
    '<li>' +
    '<input type="text" data-bind="value: type, enable:available, event: {click: $parent.addItem}" readonly/>' +
    '</li>' +
    '</ul>' +
    '</div>',
  synchronous: true
});

var types = [{
  type: "Apples",
  location: "A",
  available: true
}, {
  type: "Bananas",
  location: "A",
  available: false
}];

function Vm(data) {
  var self = this;
  self.items = ko.observableArray();
  self.types = ko.observableArray(ko.utils.arrayMap(data, function(item) {
    return item;
  }));
  self.items.addItem = function(location, type) {
    self.items.push({
      location: location,
      type: type
    });
    if (location == "A" && type == "Apples") {
      self.types()[0].available = false;
      self.types.push({
        type: 'Orange',
        location: 'B',
        available: false
      });
      self.types.valueHasMutated();
    }
  };
}

ko.options.deferUpdates = true;
var vm = new Vm(types);
ko.applyBindings(vm);