Knockoutjs.com - Hello World Example

http://knockoutjs.com/examples/helloWorld.html

by Barry Carter

HTML

<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<div>
  <div class="row">
    <div class="col-md-2">
      <h3>Providers</h3>
      <div data-bind="foreach: providers">
        <div data-bind="click: $root.selectedProvider, text: name">        
        </div>
      </div>
    </div>
    <div class="col-md-2">
      <h3>Campaigns</h3>
      <strong>Associated</strong>
      <div data-bind="foreach: campsIn">
        <div>
           <span data-bind="text: name"></span>
           <button data-bind="click: $root.campRem_click">-</button>
        </div>
      </div>
      <strong>Not Associated</strong>
      <div data-bind="foreach: campsOut">
        <div>
           <span data-bind="text: name"></span>
           <button data-bind="click: $root.campAdd_click">+</button>
        </div>        
      </div>
    </div>
    <div class="col-md-8">
      <h2>Editor</h2>
    </div>
  </div>
</div>

JavaScript

var ProvViewModel = function(name, ids) {
	this.name = ko.observable(name);
  this.campaignIds = ko.observableArray(ids);
}

var CampViewModel = function(name, id) {
	this.name = ko.observable(name);
  this.campaignId = ko.observable(id);
}

var ViewModel = function() {
	var self = this;
 
  this.providers = ko.observableArray([
  	new ProvViewModel("Prov A", [1,2]),
    new ProvViewModel("Prov B", [2,2]),
  ]);
  
  this.selectedProvider = ko.observable();
  this.camps = ko.observableArray([
  	new CampViewModel("Camp A", 1),
    new CampViewModel("Camp B", 2),
    new CampViewModel("Camp C", 3)
  ]);
  
  this.campsIn = ko.pureComputed(function() {
  		if (!self.selectedProvider())
      	return;
    	return ko.utils.arrayFilter(self.camps(), function(item) {
      	var ids = [];

      	ko.utils.arrayForEach(self.selectedProvider().campaignIds(), function(id) {
        	ids.push(id);
        });
        return ids.includes(item.campaignId());
      });
  });
  this.campsOut = this.campsOut = ko.pureComputed(function() {
  		if (!self.selectedProvider())
      	return;
    	self.selectedProvider().campaignIds();
      var ids = [];
      ko.utils.arrayForEach(self.camps(), function(camp) {
      if (!self.selectedProvider().campaignIds().includes(camp.campaignId()))
      		ids.push(camp);
      });
      return ids;
  });
  
  this.campAdd_click = function(data) {
    self.selectedProvider().campaignIds.push(data.campaignId());
  }
  
  this.campRem_click = function(data) {
    self.selectedProvider().campaignIds.remove(data.campaignId());
  }
  
};
 
ko.applyBindings(new ViewModel());