ko-add row

How do you add a row to an editable table in Knockout.js?

by mckennatim

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>
<div id="ko">
<table>
    <thead>
        <tr>
            <th>Col  1 </th>
            <th>Col  2 </th>
            <th>Col  3 </th>
            <th>Total </th>
        </tr>
    </thead>
    <tbody data-bind='foreach:List'>
        <tr>
            <!-- ko foreach:Entries-->
            <td>
                <input size="3" type="text" data-bind="value:Hours, valueUpdate:'afterkeydown'"/>
            </td>
            <!-- /ko -->
            <td>
                <span data-bind="text:Total"></span> 
            </td>
        </tr>
    </tbody>
</table>  
<button type="button" value="click" data-bind="click: addRow">addRow </button>
<h4>ko.mapping.toJSON(self.List())</h4>
<span data-bind="text: jsonList2"></span>
<h4>ko.toJSON(List,null,2)</h4>
<span data-bind="text: ko.toJSON(List, null, 2)"></span>
</div>

JavaScript

var data = {
    "Lines": [
        {"Entries": [{"Hours": 5.5},{"Hours": 2.50},{"Hours": 3.75}]}, 
        {"Entries": [{"Hours": 5.1},{"Hours": 2.00},{"Hours": 4.75}]},
        {"Entries": [{"Hours": 1.2},{"Hours": 3.00},{"Hours": 2.12}]}
    ]
}

var data1 = {"Entries": [{"Hours": 0},{"Hours": 0},{"Hours": 0}]};

function model(data){
    var self=this;
    self.Entries = ko.observableArray();
    self.Total = ko.computed(function(){
        var sum = 0;
        ko.utils.arrayForEach(self.Entries(), function(entry){
            var value = parseFloat(entry.Hours(), 10);
            if(!isNaN(value)) sum += value;
        });
        return sum;
    });
    ko.mapping.fromJS(data, {}, self);
}

var mapping = {
    create: function(options){
        return new model(options.data);
    }
}

function ViewModel() {
    var self = this

    self.List = ko.observableArray([])
    self.LoadData = function (data) {                      
        ko.mapping.fromJS(data.Lines, mapping, self.List)
    }
    self.LoadData(data);   
    self.addRow =function(){
        self.List.push(ko.mapping.fromJS(data1, mapping))
    }
    self.jsonList2=ko.computed(function(){
        var newval = ko.mapping.toJSON(self.List())
        return newval;
    });
}


ko.applyBindings(new ViewModel(), document.getElementById('ko'))