MVC 3应用程序中的基本javascript和knockout.js:针对myCustomObject项数组的循环中f
basic javascript and knockout.js in MVC 3 app: problem with for in loop over an array of myCustomObject items
问题:
我正在尝试将knockout.js与jquery模板结合使用。问题是$.ajax调用正确地返回值,但当我尝试将它们插入相应的ko.observableArray
时,我得到了正确的行数,但这些值都是undefined
根据我的调试,这个问题位于$.ajax调用的成功回调中的for in循环中。
似乎如果我写:
for (item in myArray)
{
alert(item.myProperty); // shows undefined
}
我做错了什么??!
详细设置如下。
设置:
我的模板是:
<fieldset style="padding-top:10px;">
<legend>Associated Cost Centres</legend>
<table>
<thead>
<tr>
<th>
Cost Centre
</th>
<th></th>
</tr>
</thead>
<tbody data-bind="template: {name:'actividadesAsociadas', foreach: viewModel.costCentres}"></tbody>
</table>
</fieldset>
<script type="text/x-jquery-tmpl" id="actividadesAsociadas">
<tr>
<td data-bind="text: NameCC"></td>
<td data-bind="text: CostCentreId"></td>
<td><a href="#" data-bind="click: remove">Delete</a></td>
</tr>
</script>
我的javascript是:
function costCentre(CostCentreId, IdTransactionType, NameCC, ownerViewModel) {
this.CostCentreId = ko.observable(CostCentreId);
this.IdTransactionType = ko.observable(IdTransactionType);
this.NameCC = ko.observable(NameCC);
this.remove = function() { ownerViewModel.costCentres.destroy(this) }
}
function costCentreViewModel() {
// other methods
this.costCentres = ko.observableArray([]);
var self = this;self = this;
$.ajax({url: "/[...route...]/GetCostCentres/" + @id,
dataType: 'json',
data: {},
type: 'POST',
success: function (jsonResult) {
var mappedCostCentres = $.map(jsonResult, function(item) {
return new costCentre(item.CostCentreId, item.IdTransactionType, item.Name, self)
});
for (cc in mappedCostCentres)
{
self.costCentres.push(new costCentre(cc.CostCentreId, cc.IdTransactionType, cc.NameCC, self));
}
},
error: function (result) {
$('#ErrorDisplay').show().html('<p>' + result.responseText + '</p>');
}
});
// test data
this.costCentres.push(new costCentre(55, 54, "test", this));
// other methods
};
var viewModel = new costCentreViewModel();
jQuery(document).ready(function () { ko.applyBindings(viewModel); });
javascript代码中出现问题的地方是:
for (cc in mappedCostCentres)
{
self.costCentres.push(new costCentre(cc.CostCentreId, cc.IdTransactionType, cc.NameCC, self));
}
原因是cc.CostCentreId、cc.IdTransactionType和cc.NameCC的计算结果都为undefined
。
我知道是这样的,因为jquery.tmpl模板正确地显示了测试数据,而$.ajax调用引入的行只是显示为空标记。
jsonResult:
$.ajax调用返回的jsonResult如下(这是正确的(:
[{"CostCentreId":5,"IdTransactionType":2,"Name":"Impuestos"},
{"CostCentreId":14,"IdTransactionType":3,"Name":"Transferencias Internas"}]
问题:
- 设置了for in loop(
for(cc in mappedCostCentres)
(后,为什么会:
cc.NameCC
评估为undefined
,尽管能够在firebug中看到mappedCostCentres中的项目具有我期望的值?
- 有什么更好的工作方式,或者更确切地说,从另一个数组填充一个数组
编辑:
我现在正在尝试以下代码:
在我的ViewModel(costCentreViewModel(中,我定义:
this.GetCostCentres = function() {
$.ajax({url: "/Admin/Accounts/GetCostCentres/" + @id,
dataType: 'json',
data: {},
type: 'POST',
success: function (jsonResult) {
var mapped = $.map(jsonResult, function(item) {
return new costCentre(item.CostCentreId, item.IdTransactionType, item.Name, self)
});
self.costCentres = ko.observableArray(mapped);
alert(self.costCentres.length);
},
error: function (result) {
$('#ErrorDisplay').show().html('<p>' + result.responseText + '</p>');
}
});
};
然后我调用(从视图模型定义之外(:
var viewModel = new costCentreViewModel();
viewModel.GetCostCentres();
jQuery(document).ready(function () { ko.applyBindings(viewModel); });
它仍然不起作用。我脑子里的问题是:
为什么这条线不起作用(其他都起作用(:
self.costCentres = ko.observableArray(mapped);
我只能认为这是我定义视图模型对象的方式,使用构造函数模式,即:
function myViewModel() {
this.costCentres= ko.observableArray([]);
...
this.GetCostCentres = function() {
$.ajax(....);
}
但我真的不知道。JavaScript现在正在打败我。也许我应该回到量子宇宙学?
看起来主要的问题是,当试图在AJAX请求的结果上设置observableArray的值时,您将其设置为新的observableArray,而不是设置已经绑定到UI的现有observaleArray的值。
因此,self.CostCentres
=ko.obstatileArray(已映射(`将创建一个新的observableArray,而您的UI当前没有绑定该数组。
self.CostCentres(mapped)
将是将现有的observableArray设置为等于全新阵列的适当方式。
在之前的一次尝试中,看起来你确实在构建一个CostCentre两次,以将其推送到你的observableArray上。每个CostCentre只需要创建一次。
问题主要是由于:
-
我对javascript缺乏了解。
-
复制knockoutjs.com教程,使用knocking加载和保存数据,但没有意识到教程框架缺少任何调用viewmodel对象的js代码行。
所以,当它不起作用时,我开始做一些危险的事情,这只会让我越来越深陷泥沼。
尼迈耶在问题下面的评论帮助我回到了正轨。但对于像我这样对javascript一无所知的人来说,你可以在knockoutjs.com上复制或改编教程代码,只需记住在底部添加等效的(即,取决于你的代码的作用(:
var viewModel = new costCentreViewModel();
viewModel.GetCostCentres();
jQuery(document).ready(function () { ko.applyBindings(viewModel); });
这可以有效地运行您的代码,而不是发生我无法描述或分析的奇怪事情。。。
备注
我添加了这个答案,以防有人遇到和我相同的问题,并强调什么是有效的,即遵循RP Niemeyer的建议并使事情发挥作用。
如果RP Niemeyer添加了一个答案,总结了他的建议,我将删除这个答案,并将其标记为解决方案。