如何动态添加列和行来计算敲除中每个单元格的总数

时间:2013-10-30 11:09:14

标签: javascript jquery knockout.js

我有一个像这样的简单样本数据

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}]
    }]
}

这是我的模特

function ViewModel() {
    var self = this
    self.List = ko.observableArray([])

    self.LoadData = function () {
        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}]
            }]
        }
        self.List(ko.mappings.fromJS(data.Lines))
    ////this makes every child observable
    }
    self.LoadData()
}

$('document').ready(function () {
    ko.applyBindings(new ViewModel())
}) 

这是我的观点

<table id="myTable" class="tablesorter">
    <thead>
        <tr>
            <th>Mon  1 </th>
            <th>Mon  2 </th>
            <th>Mon  3 </th>
        </tr>
    </thead>
    <tbody data-bind='foreach:Lines'>
        <tr data-bind='foreach:$data.Entries'>
            <td>
                <input type="text" data-bind="value:Hours"/>
            </td>
        </tr>
    </tbody>
</table>

以下是示例视图

enter image description here

这是我想要的输出

enter image description here

您可以看到我正在添加需要添加的列和行,这些应该是可观察的。我该怎么做。我不知道从哪里开始。

2 个答案:

答案 0 :(得分:3)

你只需要为每一行添加一个computedObservable(更新的小提琴:http://jsfiddle.net/kL79d/4/):

HTML:

<table id="myTable" class="tablesorter">
    <thead>
        <tr>
            <th>Mon  1 </th>
            <th>Mon  2 </th>
            <th>Mon  3 </th>
            <th>Total </th>
        </tr>
    </thead>
    <tbody data-bind='foreach:List'>
        <tr>
            <!-- ko foreach:Entries-->
            <td>
                <input type="text" data-bind="value:Hours, valueUpdate:'afterkeydown'"/>
            </td>
            <!-- /ko -->
            <td>
                <span data-bind="text:Total"></span> 
            </td>
        </tr>
    </tbody>
</table>

JS:

function ViewModel() {
    var self = this
    self.List = ko.observableArray([])

    self.LoadData = function () {
        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}]
            }]
        }                       
        self.List(ko.mapping.fromJS(data.Lines)())
    ////this makes every child observable
    }

    self.applyTotals = function(){
        ko.utils.arrayForEach(self.List(), function(vm){
            vm.Total = ko.computed(function(){
                var s = 0;
                ko.utils.arrayForEach(this.Entries(), function(entry){
                    var p = parseFloat(entry.Hours(), 10);
                    if (!isNaN(p)) {
                        s += p;
                    }
                });
                return s;
            }, vm);
        });
    }

    self.LoadData();
    console.log(self.List());
    self.applyTotals();
}

ko.applyBindings(new ViewModel())

要获得列总计,请在垂直方向上执行相同的操作。为了更方便地访问数据值,您可能希望将数据保存在数据结构中,以便对行和列进行简单的迭代。

答案 1 :(得分:3)

documentation for the mapping plugin中,有一个名为“使用'create'定制对象构造”的部分。这显示了如何控制json数据到可观察对象的映射 - 包括使用其他功能扩充对象(如提到的computedObservable @ pax162)。

这与@ pax162提到的方法基本相同,但是以更自动化的方式。