MVC 3 应用程序中的基本 javascript 和 knockout.js:for in 循环遍历 myCustomObject 项目数组时出现问题
问题:
我尝试将 knockout.js 与 jquery 模板一起使用。问题是 $.ajax 调用正确返回值,但是当我尝试将它们插入相应的 ko.observableArray 时,我得到了正确的行数,但值都是 根据我的调试
,问题位于 $.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 循环 (
for(cc inmappedCostCentres)
),为什么会这样:
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 现在正在打败我。也许我应该回到量子宇宙学?
Problem:
I am trying to use knockout.js with jquery templates. The problem is that an $.ajax call returns values correctly, but when I try to insert them into the corresponding ko.observableArray
, I get the correct number of rows, but the values are all undefined
The problem, according to my debugging is located in a for in loop in the success callback for an $.ajax call.
It seems that if I write:
for (item in myArray)
{
alert(item.myProperty); // shows undefined
}
What am I doing wrong??!
Detailed setup follows.
Setup:
My template is:
<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>
My javascript is:
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); });
The bit where the problem happens in the javascript code is:
for (cc in mappedCostCentres)
{
self.costCentres.push(new costCentre(cc.CostCentreId, cc.IdTransactionType, cc.NameCC, self));
}
The reason being that cc.CostCentreId, cc.IdTransactionType and cc.NameCC all evaluate to undefined
.
I know that this is the case, because the test data is displayed correctly by the jquery.tmpl template, whereas the rows that have been brought in by the $.ajax call just display as empty tags.
jsonResult:
The jsonResult returned by the $.ajax call looks like this (this is correct):
[{"CostCentreId":5,"IdTransactionType":2,"Name":"Impuestos"},
{"CostCentreId":14,"IdTransactionType":3,"Name":"Transferencias Internas"}]
Questions:
- Having set up my for in loop (
for(cc in mappedCostCentres)
), why does:
cc.NameCC
evaluate to undefined
, despite being able to see in firebug that the items in mappedCostCentres have the values that I expect?
- What better, or rather, working way is there to fill one array from another array?
Edit:
I am now trying the following code:
in my ViewModel (costCentreViewModel), I define:
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>');
}
});
};
Then I call (from outside the viewmodel definition):
var viewModel = new costCentreViewModel();
viewModel.GetCostCentres();
jQuery(document).ready(function () { ko.applyBindings(viewModel); });
It still doesn't work. The problem in my mind is:
Why doesn't this line work (everything else does):
self.costCentres = ko.observableArray(mapped);
I can only think it is the way I have defined my viewmodel object, using the constructor pattern, ie:
function myViewModel() {
this.costCentres= ko.observableArray([]);
...
this.GetCostCentres = function() {
$.ajax(....);
}
but I honestly haven't a clue. JavaScript is defeating me right now. Maybe I should go back to Quantum Cosmology?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看起来主要问题是,当尝试根据 AJAX 请求的结果设置 observableArray 的值时,您将其设置为等于新的 observableArray,而不是设置已绑定到 UI 的现有 observableArray 的值。
因此, self.CostCentres = ko.observableArray(mapped)` 将创建一个新的 observableArray,您的 UI 当前未绑定该数组。
self.CostCentres(mapped) 是将现有 observableArray 设置为等于全新数组的适当方法。
在之前的尝试中,看起来您确实构建了两次 CostCentre 以将其推送到您的 observableArray 上。每个 CostCentre 只需创建一次。
Looks like the main issue was that when trying to set the value of the observableArray on the result of an AJAX request, you were setting it equal to a new observableArray rather than setting the value of the existing one that was already bound to your UI.
So,
self.CostCentres
= ko.observableArray(mapped)` will create a new observableArray that your UI is not currently bound against.self.CostCentres(mapped)
would be the appropriate way to set an existing observableArray equal to an entirely new array.In a previous attempt, it did look like you were constructing a CostCentre twice to push it onto your observableArray. It is only necessary to create each CostCentre once.
该问题主要是由于:
我缺乏 javascript 知识。
复制knockoutjs.com教程以使用knocking加载和保存数据,但没有意识到教程框架缺少任何js代码行来调用viewmodel对象。
因此,当它不起作用时,我就开始了一些转移注意力的活动,这只会让我在泥沼中越陷越深。
尼迈耶在问题下面的评论帮助我回到正轨。但是对于任何与我一样对 javascript 无知程度相似的人,您可以复制或改编 knockoutjs.com 上的教程代码,只需记住在底部添加等效项(即,取决于您的代码的作用):
这有效地运行您的代码,而不是发生奇怪的事情,我没有能力描述或分析...
请注意,
我添加了这个答案,以防有人遇到与我相同的问题,并强调什么是有效的,如下RP Niemeyer 的建议和让事情发挥作用。
如果 RP Niemeyer 添加了一个答案,总结了他的建议,我将删除该答案并将其标记为解决方案。
The problem has largely been due to:
my lack of knowledge of javascript.
copying the knockoutjs.com tutorial for loading and saving data using knocking and not realising that the tutorial framework was missing any lines of js code to call the viewmodel object.
So when it didn't work, I set off on a number of red herrings that just drove me deeper and deeper into the mud.
Niemeyer's comments below the question helped me to get back on track. But for anyone with similar levels of javascript ignorance as me, you can copy or adapt the tutorial code on knockoutjs.com, just remember to add, at the bottom the equivalent of (ie, depending on what your code does):
This effectively runs your code, as opposed to odd things happening, that I am not equipped to describe or analyse...
Note
I have added this answer in case anyone comes looking with the same problem as me, and to hightlight what did work, which was following RP Niemeyer's suggestions and getting the thing to work.
If RP Niemeyer adds an answer, summarising his suggestions, I will delete this answer and mark his as the solution.