使用 KnockoutJS 对带有对象的下拉菜单进行初始选择

发布于 2025-01-08 09:23:31 字数 775 浏览 0 评论 0原文

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

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

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

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

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

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

我该怎么做?

I have a model that looks something like this (not actual code so don't mind the possible mistyping).

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

The options coantains list of objects that one can select from in a dropdown. The items also contains a list of object where each object has a identical object like one in the options-list.

I then foreach over the items list and display an dropdown box on each row. I here need the object in the current items from the items list to be the selected option. When I however don't set an optionValue but only try to match on whole object it doesn't work ... My observable then however works fine and all the subscribing fields for the whole object get updated with the new selection. I however got the initial selection to work with optionValue and Id like below.

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

My problem now is that only the element bound to the Id gets updated? I need to have all the properties of the current item updated even if it's only the Id that changes now when I change something in the dropdown.

How should I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

只有一腔孤勇 2025-01-15 09:23:31

所以我对此的看法如下。

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

与 c# 和其他高级环境不同,javascript 没有内置的相等概念。当您执行诸如 objA == objB 之类的操作时,它将检查引用是否相等(对于数字和字符串等基本类型而言并非如此),即这两个变量实际上引用了同一个对象。例如,在 .NET 中,类可以实现 IEquatable (和运算符重载),以便 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 参数中包含的选项与选项属性中的选项完全相同,knockout 现在可以比较它们是否相等,您可以在绑定中使用它,如下所示:

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

在 jsfiddle 上测试它: http://jsfiddle.net/niik/HDsKC/

So my take on this is the following.

  • You have a set of 'options'. Each option has some properties and an Id
  • You have a set of 'items' where each item has one property containing an object which equals one of the objects inside options. So each 'item' has a selected 'option'.

Unlike c# and other high-level environments javascript does not have a built-in concept of equality. When you do something like objA == objB it will check for reference equality (not true for primitive types such as numbers and strings), ie that the two variables actually reference the same object. In .NET for example a class could implement IEquatable<T> (and a operator overload) so that objA == objB results in some custom comparison which will determine whether or not the two different objects could be considered equal.

So when working with knockout and drop down and such it's important to remember that in order for knockout to match you'll have to ensure that the compared objects are indeed the same.

In your case I've tweaked your model a bit. I've assumed that the selection option property of items is called 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(); })
        );
    });
}

Since you're using ko.mapping I'm assuming that the options and items parameters are provided as plain javascript objects somehow (Ajax, inline 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);

Since the options contained in the SelectedOption parameter of each item is the exact same as the ones in the options property knockout is now able to compare them for equality and you can use it in your bindings as such:

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

Test it out at jsfiddle: http://jsfiddle.net/niik/HDsKC/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文