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

本文关键字:myCustomObject 针对 数组 js 循环 应用程序 MVC javascript knockout      更新时间:2023-09-26

问题:

我正在尝试将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"}]

问题:

  1. 设置了for in loop(for(cc in mappedCostCentres)(后,为什么会:

cc.NameCC

评估为undefined,尽管能够在firebug中看到mappedCostCentres中的项目具有我期望的值?

  1. 有什么更好的工作方式,或者更确切地说,从另一个数组填充一个数组

编辑:

我现在正在尝试以下代码:

在我的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只需要创建一次。

问题主要是由于:

  1. 我对javascript缺乏了解。

  2. 复制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添加了一个答案,总结了他的建议,我将删除这个答案,并将其标记为解决方案。