【问题标题】:Save JS object to Knockout Array将 JS 对象保存到 Knockout Array
【发布时间】:2014-09-30 00:26:13
【问题描述】:

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

我想要做的是拥有用户从旧会话中保存的先前数据,并从他们离开的地方继续,而不必再次重做所有事情。因此,我正在加载所有旧数据,并通过为它们预先选择选项将其放回原来的位置。

这是我目前拥有的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

感谢我能得到的任何帮助。

【问题讨论】:

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


    【解决方案1】:

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

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

    解决此问题的一种方法是将 optionsValue 和 value 都设置为 '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/

    只有 Bengals 和 Broncos 被选中,因为它们是 AfcTeams 和 AfcSelectedWildCards 之间唯一匹配的球队。

    【讨论】:

    • 你能创建一个显示问题的小提琴吗?也许使用echo返回模拟数据?
    • 对不起,我确实声明了自己,但我忘了把它放进小提琴里。我试着按照你说的做,当 JSON 对象被硬编码到 ViewModel 中时,它似乎工作正常。但是当我从服务器上抓取它时,它就不起作用了。另一个问题是,在第一个面板中选择的任何内容都应该成为另一个面板中的选项。这以前有效,但现在无效。我更新了Fiddle 以反映这一点。这是选定团队的工作版本,可用于另一个小组Fiddle
    • 您能否详细解释所需的用户交互?顶部的两个选择代表外卡球队?在两个顶级选择中选择的团队应该出现在其余选择中?
    • 所以前两个选择和下一个面板都是外卡团队的一部分。底部最后一个带有“#”代替数字输入的面板将仅包含从外卡团队中选择的选项。我也添加了回声,它显示了我目前遇到的相同问题Fiddle
    【解决方案2】:

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

    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);
    

    【讨论】:

      猜你喜欢
      • 2015-09-11
      • 2014-09-17
      • 1970-01-01
      • 2014-10-01
      • 2014-11-27
      • 2013-11-22
      • 2013-11-10
      • 2012-03-23
      • 2015-02-03
      相关资源
      最近更新 更多