【问题标题】:Knockout.js updating array within an arrayKnockout.js 更新数组中的数组
【发布时间】:2012-11-18 16:38:18
【问题描述】:

我在 Knockout 视图模型中有一个数组,看起来像这样:

this.Activities = ko.observableArray([
{ "date": "28/11/2012 00:00:00",
  "activities": [
     { "company": "BOW",
       "description": "Backup Checks",
       "length": "60"
     },
     { "company": "AMS",
       "description": "Data Request",
       "length": "135"
     },
  ]},
{ "date": "30/11/2012 00:00:00",
  "activities": [
     { "company": "BOW",
       "description": "Backup Checks",
       "length": "60"
     },
     { "company": "SLGT",
       "description": "Software Development",
       "length": "240"
     },
     { "company": "BOW",
       "description": "Data Request",
       "length": "30"
     },
  ]},
]);

我使用这段代码向它添加一个新元素:

this.Activities.push(new NewActivity(company, description, length, fullDate));

其中使用NewActivity函数:

function NewActivity(company, description, length, date) {
    this.date = date;
    this.activities = [{ "company": company, "description": description, "length": length }];
}

而且效果很好。但是,它每次被释放时都会创建一个全新的对象。当代码检查已创建对象的日期时,我需要实现一个条件。如果新创建的对象具有相同的日期,则应将活动详细信息添加到该日期的活动数组中的活动数组中。

我该怎么做?

Activities 数组的所有数据都来自 MVC 应用程序中强类型视图中的模型:

this.Activities = ko.observableArray([
        @foreach (ActivitySet aSet in Model)
        {
            @:{ "date": "@aSet.Date",
            @:"activities": [
                 foreach(Activity a in aSet.Activities)
                 {
                     @:{ "company": "@a.Companies.Select(c => c.Title).Single()",
                       @:"description": "@a.Descriptions.Select(c => c.Title).Single()",
                       @:"length": "@a.LengthInMinutes"
                     @:},
                 }
            @:]},
        }
]);

【问题讨论】:

    标签: javascript model-view-controller mvvm knockout.js


    【解决方案1】:

    我建议您创建一些实体来描述您的活动:

    // Details
    function ActivityDetails(company, description, length) {
        this.company = ko.observable(company);
        this.description = ko.observable(description);
        this.length = ko.observable(length);
    }
    
    // Activity
    function Activity(date, activityDetails) {
        this.date = ko.observable(date);
        this.details = ko.observableArray(activityDetails);
    }
    

    您可以通过以下方式控制活动:

    function ViewModel () {
        var self = this;
    
        this.Activities = ko.observableArray([
            // Activities here
        ]);
    
        this.addActivity = function (activity) {
            var flag = false;
            ko.utils.arrayMap(self.Activities(), function (item) {
                // Flag is here so it doesn't keep checking further in iterations
                if (!flag) {
                    if (item.date() === activity.date()) {
                        item.details.push(activity.details);
                        flag = true;
                    }
                }
            });
            // Case where activity date was not found in existing records
            if (!flag) {
                self.Activities.push(activity);
            }
        }
    }
    

    这要求您的视图模型有一个自定义添加方法,我已经提供了一个示例。请注意,我在任何地方都在解析可观察值,因此如果您使用不可观察值,请删除函数调用。

    【讨论】:

    • 谢谢,我试试。看起来很有希望
    • 我明白你答案背后的逻辑。不幸的是 AddActivity 功能对我不起作用。此行不执行: ko.utils.arrayMap(self.Activities, function (item) 代码只是通过它而不进入函数!
    • @Bartosz 是的,它应该是 self.Activities() 而不是 self.Activities。更正了答案。
    • 是的,我自己找到了它,但它仍然不适合我。所以我找到了另一个解决方案: ko.utils.arrayForEach(this.Activities(), function(feature) { if(feature.date == activity.date()) { feature.details.push(new ActivityDetails(company, description,长度));标志=真;}});这次push方法对我不起作用!?%##"^~~# WHYYY
    • @Bartosz 据我所知,根据您的代码无法观察到您的日期。如果不是,则使用 feature.date,否则使用 feature.date()。在我提供的代码示例中究竟有什么不起作用?
    猜你喜欢
    • 1970-01-01
    • 2012-06-30
    • 2017-11-09
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    相关资源
    最近更新 更多