Initial selection on dropdowns with objects using KnockoutJS

被刻印的时光 ゝ 提交于 2019-12-06 06:31:59

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/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!