将JS对象保存到Knockout Array

时间:2014-08-06 22:06:13

标签: javascript jquery asp.net-mvc data-binding knockout.js

所以我试图通过AJAX调用从服务器加载JSON。我能够很好地将它映射到以HTML格式绑定的数组中。这些对象将保存到一个数组中,该数组将用作select标记的值。如果我向控制台输出数组中的内容,则所有对象都显示正常。但是这些对象并不像在选择框中预选的那样显示。

我尝试做的是拥有用户从旧会话中保存的先前数据,并在他们停止的地方继续,而无需再次重做所有内容。所以我通过预先选择它们的选项来加载所有旧数据并将其放回原来的位置。

这是我目前拥有的JS:

function BracketsViewModel() {
self.AfcTeams = ko.observableArray([]);

// Normally pulled from server via AJAX with more teams. Hardcoded for simplicity
self.AfcTeams.push(new TeamModel({
    Tricode: "CIN",
    DisplayName: "Bengals"
}));
self.AfcTeams.push(new TeamModel({
    Tricode: "BUF",
    DisplayName: "Bills"
}));
self.AfcTeams.push(new TeamModel({
    Tricode: "DEN",
    DisplayName: "Broncos"
}));
self.AfcTeams.push(new TeamModel({
    Tricode: "CLE",
    DisplayName: "Browns"
}));
self.AfcTeams.push(new TeamModel({
    Tricode: "SD",
    DisplayName: "Chargers"
}));

// Temporary array that holds Team object
self.AfcSelectedWildCards = [];
for (var i = 0; i <= 5; i++) {
    self.AfcSelectedWildCards.push(ko.observable());
}

// Holds selected teams that go to next round
self.AfcDivisionals = ko.computed(function () {
    var tmp = [];
    ko.utils.arrayForEach(self.AfcSelectedWildCards, function (team) {
        if (team()) {
            tmp.push(team());
        }
    });

    return tmp;
});

// Other properties not shown for simplicity
// This will be loaded from server via AJAX call
var bracketsObject = {
    AfcTeams: [{
        Tri: "CIN",
        Name: "Bengals",
        Rank: "1"
    }, {
        Tri: "HOU",
        Name: "Texans",
        Rank: "2"
    }, {
        Tri: "NE",
        Name: "Patriots",
        Rank: "3"
    }, {
        Tri: "NYJ",
        Name: "Jets",
        Rank: "5"
    }, {
        Tri: "DEN",
        Name: "Broncos",
        Rank: "4"
    }, {
        Tri: "KC",
        Name: "Chiefs",
        Rank: "6"
    }]
};

var afcteams = $.map(bracketsObject.AfcTeams, function (team) {
    return new AltTeamModel(team);
});

// Saving objects to array that is being binded in HTML
for (var i = 0; i <= 5; i++) {
    self.AfcSelectedWildCards[i] = ko.observable(afcteams[i]);
}
}

function TeamModel(data) {
if (data) {
    this.Tri = data.Tricode;
    this.Name = data.DisplayName;
} else {
    this.Tri = "";
    this.Name = "";
}
this.Rank = ko.observable(0);
}

function AltTeamModel(data) {
    this.Tri = data.Tri;
    this.Name = data.Name;
    this.Rank = ko.observable(data.Rank);
}

ko.applyBindings(new BracketsViewModel());

以下是Fiddle

我感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

第一个问题是你引用了self,但从未声明过它。您需要在BracketsViewModel顶部添加var self = this;

下一个问题是AfcTeams是一个可观察的TeamModel数组,但AfcSelectedWildCards是一个AltTeamModel数组。它们需要与选项和值匹配的视图模型相同。

解决这个问题的一种方法是将optionsValue和值都设置为'Tri',如下所示:

<select class="form-control"
        data-bind="options: AfcTeams,
        optionsText: 'Name',
        optionsCaption: '-- Team --',
        optionsValue: 'Tri',
        value: AfcSelectedWildCards[0]().Tri"></select>

以下是这两个修正案的小提琴:http://jsfiddle.net/qpolarbear/8kkamzy7/

只选择孟加拉虎队和野马队,因为他们是AfcTeams和AfcSelectedWildCards之间唯一匹配的队伍。

答案 1 :(得分:0)

所以在从这个项目中休息之后,我终于找到了如何绑定通过AJAX加载的对象。问题是Knockout在AJAX调用完成之前绑定了文档,因此无论出于何种原因,绑定都没有反映出这些变化。我决定做的是将文档超出应用绑定并首先从服务器加载所有内容。然后,我将所有对象传递到View Model中,并在半秒延迟时应用绑定。现在一切都很好。这是代码:

function TeamModel(data, isPreData) {
    if (isPreData) {
        this.Tri = data.Tri;
        this.Name = data.Name;
        this.Rank = ko.observable(data.Rank);
    } else {
        if (data) {
            this.Tri = data.Tricode;
            this.Name = data.DisplayName;
        } else {
            this.Tri = "";
            this.Name = "";
        }
        this.Rank = ko.observable(0);
    }
}

var afcteams;
$.getJSON('/Brackets/GetBrackets', { id: someId}, function (bracketsObject) {
    if (bracketsObject) {
        afcteams = $.map(bracketsObject.AfcTeams, function (team) {
            return new TeamModel(team, true);
    });
}
}).fail(function () {
    alert("There was an error getting data from the server.");
});

var teams;
$.getJSON('/Brackets/GetAFCTeams', function (data) {
    teams = $.map(data, function (team) {
        return new TeamModel(team, false);
    });
});

function SetBindings(afcteams, teams) {
    ko.applyBindings(new BracketsViewModel(afcteams, teams));
}

setTimeout(function() {
    SetBindings(afcteams, teams);
}, 500);