0

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

我有一个表,并且正在使用数据绑定属性中的 foreach 外观,该属性循环通过淘汰视图模型并创建行。

在视图模型中,我添加了更多属性来支持一个新的页脚行,该行合计表中的数字列。

不幸的是,当我回发到控制器时,我在视图模型中添加的属性导致一行被删除。我怀疑我使用了错误的淘汰赛结构来添加这些总数......

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

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);
});
4

2 回答 2

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>
于 2013-06-03T21:48:03.383 回答
0

使用敲除 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

于 2013-06-04T17:01:52.570 回答