2

我有一个看起来像这样的模型(不是实际代码,所以不要介意可能的错误输入)。

model = function(option, items) {
    self = this;
    self.options = options;
    self.items = ko.mapping.fromJS(items);
}

可以在下拉列表中选择的对象options容器列表。还包含一个对象列表,其中每个对象都具有与选项列表中的对象相同的对象。items

然后我遍历项目列表并在每一行显示一个下拉框。我这里需要将项目列表中当前项目中的对象作为选定选项。但是,当我没有设置 optionValue 而是仅尝试匹配整个对象时,它不起作用......我的 observable 然后可以正常工作,并且整个对象的所有订阅字段都会使用新的选择进行更新。然而,我得到了与 optionValue 一起使用的初始选择,Id如下所示。

<select data-bind="options: $parent.options, optionsValue:'Id', optionsText: 'Name', value: item.Id"></select> 

我现在的问题是只有绑定到 Id 的元素才会更新?我需要更新当前项目的所有属性,即使当我在下拉列表中更改某些内容时它只是现在更改的 Id。

我该怎么做?

4

1 回答 1

6

所以我对此的看法如下。

  • 您有一组“选项”。每个选项都有一些属性和一个 Id
  • 您有一组“项目”,其中每个项目都有一个属性,其中包含一个对象,该对象等于选项中的一个对象。所以每个“项目”都有一个选定的“选项”。

与 c# 和其他高级环境不同,javascript 没有内置的相等概念。当您执行类似操作objA == objB时,它将检查引用相等(对于数字和字符串等原始类型不正确),即这两个变量实际上引用了同一个对象。例如,在 .NET 中,一个类可以实现IEquatable<T>(和一个运算符重载),从而objA == objB导致一些自定义比较,这将确定两个不同的对象是否可以被视为相等。

因此,在使用淘汰赛和下拉等时,重要的是要记住,为了让淘汰赛匹配,您必须确保比较的对象确实相同。

在您的情况下,我对您的模型进行了一些调整。我假设项目的选择选项属性称为SelectedOption

function model(options, items) {
    self = this;
    self.options = options;  
    self.items = ko.mapping.fromJS(items);

    // Loop over each of the items and swap out the server-side provided option object
    // with the corresponding option from the options parameter.
    ko.utils.arrayForEach(self.items(), function(item) {
        item.SelectedOption = ko.observable(
            ko.utils.arrayFirst(self.options, function(option) { return option.Id == item.SelectedOption.Id(); })
        );
    });
}

由于您使用的是 ko.mapping 我假设选项和项目参数以某种方式作为普通 javascript 对象提供(Ajax,内联 js)。

opts = [ 
    { Id: 1, Name: "Option 1" },
    { Id: 2, Name: "Option 2" },
    { Id: 3, Name: "Option 3" }
];

var items = [
    { Id: 1, Name: "Item 1", SelectedOption: { Id: 1, Name: "Option 1" } },
    { Id: 2, Name: "Item 2", SelectedOption: { Id: 2, Name: "Option 2" } },
    { Id: 3, Name: "Item 3", SelectedOption: { Id: 3, Name: "Option 3" } }
];

var viewModel = new model(opts, items);

由于每个项目的 SelectedOption 参数中包含的选项与选项属性中的选项完全相同,因此淘汰赛现在能够比较它们是否相等,您可以在绑定中使用它,如下所示:

<div data-bind="foreach: items">
    <select data-bind="options: $parent.options, optionsText: 'Name', value: SelectedOption"></select>
</div>

在 jsfiddle 进行测试:http: //jsfiddle.net/niik/HDsKC/

于 2012-02-24T17:53:55.047 回答