Knockoutjs从json填充数据计算变量

时间:2015-02-09 16:13:03

标签: javascript json knockout.js ko.observablearray computed-observable

我目前正在试验一下淘汰赛和javascript,但只是遇到了一个我无法解决的问题。

我有一个viewmodel有几个(简单,因为这只是用于测试)子虚拟机,其中一个有一个计算变量,它应该显示另一个虚拟机阵列的聚合成本。

当我通过json加载数据时,一切都很好地填充,但计算的仍然是“未定义”。我已经尝试用“deferEvaluation”标记计算,但这没有帮助。

这里简短来说就是我的jsfiddle http://jsfiddle.net/v73rxckf/9/

任何想法?或者我一般做错了什么?

JS代码:

function Service(data) {
    var self = this;

    self.Cost = ko.observable(data.Cost);
}

function Action(data) {
    var self = this;

    self.Name = ko.observable(data.Name);
    self.Dates = ko.observableArray(data.Dates);
    self.Services = ko.observableArray(data.Services);

    self.OverallCost = ko.computed(function() {
        calculated = 0;

        ko.utils.arrayForEach(self.Services(), function(item) {
            calculated += parseFloat(ko.utils.unwrapObservable(item.Cost));
        });

        return calculated;
    }, { deferEvaluation : true });

}

function Campaign(data) {

    var self = this;

    self.Name               = ko.observable(data.Name);
    self.Deadline           = ko.observable(data.Deadline);
    self.ActionList         = ko.observableArray(data.ActionList);
}

function ApplicationViewModel () {

    var self = this;
    self.List = ko.observableArray([]);

    $.ajax("/echo/json/", {
        data: {
            json: ko.toJSON(fakeData)
        },
        type: "POST",
        dataType: 'json',
        success: function(data) {
            var mappedCampaigns = $.map(data, function(item) {
                return new Campaign(item);
            });

            self.List(mappedCampaigns);
        }
    });
}

var fakeData = [{
    "Name":"testname1",
    "Deadline":"testdeadline1",
    "ActionList":[
                    {
                        "Name":"testaction1",
                        "Dates":[ { "DateValue":"testdate1" }, { "DateValue":"testdate2" } ],
                        "Services":[ { "Cost":"100" }, { "Cost":"50" } ]
                    },
                    {
                        "Name":"testaction2",
                        "Dates":[ { "DateValue":"testdate1" }, { "DateValue":"testdate2" } ],
                        "Services":[{ "Cost":"100" }, { "Cost":"50" } ]
                    }
                ]
}];

ko.applyBindings(new ApplicationViewModel());

2 个答案:

答案 0 :(得分:0)

您没有映射ActionList,而只是使用了json数据。

var mappedActions = $.map(data.ActionList, function(item) {
    return new Action(item);
});

self.ActionList = ko.observableArray(mappedActions);

JsFiddle

答案 1 :(得分:0)

您没有初始化您的操作对象,您需要在广告系列视图模型中新建您的操作视图模型并将其推送到可观察数组中:

function Campaign(data) {

    var self = this;

    self.Name               = ko.observable(data.Name);
    self.Deadline           = ko.observable(data.Deadline);
    self.ActionList         = ko.observableArray([]);

    if(data.ActionList){
        for(var i = 0; i < data.ActionList.length; i++){
            self.ActionList.push(new Action(data.ActionList[i]));
        }
    }
}

您还需要为服务视图模型执行相同的操作。 e.g:

function Service(data) {
    var self = this;

    self.Cost = ko.observable(data.Cost);
}

function Action(data) {
    var self = this;

    self.Name = ko.observable(data.Name);
    self.Dates = ko.observableArray(data.Dates);
    self.Services = ko.observableArray([]);

    if(data.Services){
        for(var i = 0; i < data.Services.length; i++){
            self.Services.push(new Service(data.Services[i]));
        }
    }

    self.OverallCost = ko.computed(function() {
        calculated = 0;

        ko.utils.arrayForEach(self.Services(), function(item) {
            calculated += parseFloat(ko.utils.unwrapObservable(item.Cost));
        });

        return calculated;
    });

}