我正在尝试对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);
});
答案 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