Array mapping issue

Example of using mapping to add observable to an array element

by Scott Goodwin

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<ul data-bind="foreach:products">
  <li>
    <span data-bind="text:Name"></span>
    <a data-bind="click: ViewProductDetails" href="#">View Details</a>
  </li>
</ul>

<button id="BtnLoadData">Load Data From Server</button>

<div id="ProductDetails" data-bind="with: selectedProduct">
  <h1>Selected Product</h1>
  Name: <span data-bind="text: Name"></span><br/>  
  Price: <span data-bind="text: Price"></span><br/>
  Color: <span data-bind="text: Color"></span>
</div>

JavaScript

var viewModel = {
  products: ko.observableArray([]),
  selectedProduct: ko.observable()
};

var productMapping = {
  create: function(options) {
  	var self = ko.mapping.fromJS(options.data, {observe: [""]} );
    self.ViewProductDetails = function() {    	
			viewModel.selectedProduct(self);
    	$('#ProductDetails').show();
    };
    return self;
  }
};

var jsonFromServer = [{
  Name: "Hat",
  Price: "123.45",
  Color: 'Red'
}, {
  Name: "Coat",
  Price: "23.45",
  Color: 'Blue'
}, {
  Name: "Jacket",
  Price: "234.45",
  Color: 'Green'
}];

$('#ProductDetails').hide();
$('document').ready(function() {

  $('#BtnLoadData').click(function() {
    ko.utils.arrayForEach(jsonFromServer, function(item) {
      viewModel.products.push(ko.mapping.fromJS(item, productMapping));
    });
  });
	
  ko.applyBindings(viewModel);
})