Observable array

by rniemeyer

HTML

<div id="test">
  <table>
    <thead>
      <tr>
          <td></td>
        <td>Week 1</td>
        <td>Week 2</td>
        <td>Week 3</td>
      </tr>
    </thead>
    <tbody> 
<tr>
    <td>subtotal</td>
    <td data-bind="text: week1Sum"></td>
    <td></td>
        <td></td>
        </tr>    
        <!-- ko foreach: revenueStreams -->
      <tr>
        <td>Name</td>
        <td><input data-bind="value: week1Amount.formatted" /></td>
        <td><input data-bind="value: week2Amount.formatted" /></td>
        <td><input data-bind="value: week3Amount.formatted" /></td>
      </tr>
        <!-- /ko -->
    </tbody>
  </table>
      <p data-bind="text: $root.revenueStreams[0].week1Amount"></p>
  </div>

JavaScript

ko.observable.fn.withCurrencyFormat = function(precision) {
    var observable = this;
    observable.formatted = ko.computed({
        read: function (key) {
            return '$' + (+observable()).toFixed(precision);
        },
        write: function (value) {
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            observable(isNaN(value) ? null : value); // Write to underlying storage 
        }        
    }); 

    return observable;
};


function revenueStream(w1, w2, w3) {
  var self = this;
  self.week1Amount = ko.observable(w1).withCurrencyFormat(2);
  self.week2Amount = ko.observable(w2).withCurrencyFormat(2);
  self.week3Amount = ko.observable(w3).withCurrencyFormat(2);
  }

function revenueStreamCategory(revenueStreams) {
  var self = this;
  self.revenueStreams = revenueStreams;
  
  self.week1Sum = ko.computed(function () {
    var sum = 0.0;
      
    ko.utils.arrayForEach(self.revenueStreams, function(item) {
            sum += +item.week1Amount();
    });      
      return sum;
  });    
}

    var rs = []
    rs.push(new revenueStream(10, 11, 12));
    rs.push(new revenueStream(13, 14, 15));    
    rs.push(new revenueStream(16, 17, 18));

    var vm = new revenueStreamCategory(rs);      
    
ko.applyBindings(vm, document.getElementById("test"));