由于淘汰代码而删除表行

时间:2013-06-03 21:31:05

标签: knockout.js

我正在尝试对ASP.NET MVC 4应用程序进行一些增强,这些应用程序在浏览器中大量使用了knockout.js和MVVM模式。我正在接受淘汰赛,我真的很喜欢它,但我设法引起了一个意想不到的错误。

我有一个表,并且在data-bind属性中使用foreach外观,该属性循环遍历一个knockout viewmodel并创建行。

在viewmodel中,我添加了一些属性来支持新的页脚行,该行总计表中的数字列。

不幸的是,我在viewmodel中添加的属性导致在我回发到控制器时删除了一行。我怀疑我使用错误的敲除构造来添加这些总数...

...这是在视图模型中......

self.BudgetTotal = ko.computed(function () {
    var total = 0;
    //The problem is this loop! It's messing with the Phases observable array and it's all magic behind the scenes and I can't see what's going wrong
    for (i = 0; i < self.Phases().length; i++)
        total = parseFloat(total) + parseFloat(self.Phases()[i].Total());
    return format_number(total, 2);
});

这是表格:

<table class="table table-bordered table-compact">
                <thead>
                    <tr>
                        <th></th>
                        <th>Phase</th>
                        <th>Name</th>
                        <th>Phase Manager</th>
                        <th>Labor</th>
                        <th>Expense</th>
                        <th>Subs</th>
                        <th>Total</th>
                    </tr>
                </thead>
                <tbody data-bind="template: {foreach: Phases.sort(function (l, r) { return l.Code() > r.Code() ? 1 : -1 }) }">
                    <tr>
                        <td><input type="checkbox" data-bind="checked: IsSelected, click:SelectionChanged"/></td>
                        <td class="phasecode" data-bind="text: Code"></td>
                        <td><input type="text" data-bind="value: Name, visible: IsAdditional" class="input-small phaseName" maxlength = "35"/><span data-bind="text: Name, visible: !IsAdditional()"></span></td>
                        <td><input type="hidden" id="CompanyCode" data-bind="value: Company().Code" /><input type="text" class="PhaseManagerTypeahead phaseManager" data-bind="value: PhaseManager().CodeName, enable: IsSelected" autocomplete="off"/></td>
                        <td>
                            <nobr><input class="span1" id="inputIcon" type="text" data-bind="value: Labor, enable: IsSelected" style="text-align:right" onblur="checkDecimal(this)" maxlength = "20"/></nobr>
                        </td>
                        <td>
                            <nobr><input class="span1" id="inputIcon" type="text" data-bind="value: Expenses, enable: IsSelected" style="text-align:right" onblur="checkDecimal(this)" maxlength = "20"/></nobr>
                        </td>
                        <td>
                            <nobr><input class="span1" id="inputIcon" type="text" data-bind="value: Subcontractor, enable: IsSelected" style="text-align:right" onblur="checkDecimal(this)" maxlength = "20"/></nobr>
                        </td>
                        <td data-bind="text: Total" style="min-width:80px; text-align:right"></td>
                    </tr>                                            
                </tbody>
                <tfoot class="hideFromPrinter">
                    <tr>
                        <td colspan="8"><a href="javascript:void(0);" data-bind='click: viewModel.addAdditionalPhase'>Add Additional Phase...</a></td>
                    </tr>
                </tfoot>
            </table>

我删除了显示总计的页脚行,但发现它与错误无关。如果我注释掉上面的淘汰代码,那么这个bug就会消失。当我取消注释它时,错误返回。

解决方案是使用实用程序函数arrayForEach迭代可观察数组。

self.BudgetTotal = ko.computed(function () {
var total = 0;
ko.utils.arrayForEach(self.Phases, function (item) {
    var value = parseFloat(item.Total());
    if(!isNaN(value))
        total += value;
    }
);
return total.toFixed(2);
});

2 个答案:

答案 0 :(得分:1)

您的绑定是问题所在。您说您绑定到模板,但没有指定模板名称。只需使用foreach绑定它就可以了:

  <tbody data-bind="foreach: Phases">
   <tr>...</tr>
  </tbody>

或指定模板名称:

  <tbody data-bind="template: { foreach: Phases, name: 'row-template'}">
  </tbody>

  <script type="text\html" id="row-template">
    <tr>...</tr>
  </script>

答案 1 :(得分:0)

使用knockouts arrayForEach解决了这个问题:

self.BudgetTotal = ko.computed(function () {
    var total = 0;
    ko.utils.arrayForEach(self.Phases, function (item) {
        var value = parseFloat(item.Total());
        if(!isNaN(value))
            total += value;
    );
    return total.toFixed(2);
});

谷歌搜索引导我到这个块,建议使用arrayForEach。

http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html