最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Selecting default option value with knockout - Stack Overflow

programmeradmin0浏览0评论

I'm trying to select a default select option based on one of the property with which I'm populating my select option.

This code is copied straight from @rneimeyer's fiddle. I did tweak it to do what I wanted to do.

So, I have choices as my observableArray.

var choices = [
    { id: 1, name: "one", choice: false },
    { id: 2, name: "two", choice: true },
    { id: 3, name: "three", choice: false }
    ];

function ViewModel(choices, choice) {
   this.choices = ko.observableArray(choices);
};

The difference between rneimeyer's fiddle and mine is that I have choice property added on my object inside the observableArray instead of having a separate observable for the option that we want to be default.

Here's the fiddle on my attempt.

Now I'm checking in my select element tag whether the choice attribute is true or not. And if it is then I want to set the name to the value attribute so that it becomes the default.

<select data-bind="options: choices, optionsText: 'name', value: choice"></select>

I've tested this with simple data model in my fiddle here as well which is working just as I wanted.

I guess what my real query is how to check choice property in the data-bind. I see that optionText is being able to access the name property just fine. Not sure why it isn't same for choice property in value attribute.

I'm trying to select a default select option based on one of the property with which I'm populating my select option.

This code is copied straight from @rneimeyer's fiddle. I did tweak it to do what I wanted to do.

So, I have choices as my observableArray.

var choices = [
    { id: 1, name: "one", choice: false },
    { id: 2, name: "two", choice: true },
    { id: 3, name: "three", choice: false }
    ];

function ViewModel(choices, choice) {
   this.choices = ko.observableArray(choices);
};

The difference between rneimeyer's fiddle and mine is that I have choice property added on my object inside the observableArray instead of having a separate observable for the option that we want to be default.

Here's the fiddle on my attempt.

Now I'm checking in my select element tag whether the choice attribute is true or not. And if it is then I want to set the name to the value attribute so that it becomes the default.

<select data-bind="options: choices, optionsText: 'name', value: choice"></select>

I've tested this with simple data model in my fiddle here as well which is working just as I wanted.

I guess what my real query is how to check choice property in the data-bind. I see that optionText is being able to access the name property just fine. Not sure why it isn't same for choice property in value attribute.

Share Improve this question edited Jan 15, 2014 at 20:02 shriek asked Jan 15, 2014 at 19:46 shriekshriek 5,8238 gold badges51 silver badges82 bronze badges 3
  • 1 The difference between rneimeyer's fiddle and mine is that I have choice property added on my object inside the observableArray instead of having a separate observable for the option that we want to be default. Why? What's wrong with the other approach? What problem are you trying to solve by doing it like this? – Matt Burland Commented Jan 15, 2014 at 20:16
  • The difference is how the data is being passed to me by the service. The service is giving me all the information in one chunk rather than have an object that only has the default option. – shriek Commented Jan 15, 2014 at 20:25
  • So? When you get the data from your service, you run through it and pull out the one that has choice === true and put it in your selectedOption observable. As it currently stands, it's not going to work because choice isn't an observable anyway and you have the problem that you can't change choice on two entries at once so you will have a situation where either two options are chosen or no options are chosen. – Matt Burland Commented Jan 15, 2014 at 20:39
Add a comment  | 

4 Answers 4

Reset to default 10

I might have misdirected to some people. Also, I apologize for not mentioning the version that I'm using. I'm currently using Knockout 3.0.0 (you'll see why this is important later)

Also, just to note that I'm not saying @XGreen's method is wrong but that wasn't exactly what I was looking for and this might be due to my poor explanation.

Let me first try to clarify what I was trying to accomplish. First of all, I will be having an array of object with the information for the options.

[
 { id: 1, name: "one", choice: false },
 { id: 2, name: "two", choice: true },
 { id: 3, name: "three", choice: false }
]

Now, what I wanted to do was to data-bind select option to that array with choice true being the default selected one.

I'm not intending to create any extra observable except the array itself which is going to be an observableArray.

After much research I finally found optionsAfterRender attribute for options property in Knockout's Docs.

<select data-bind="options: choices, 
                   optionsValue: 'name',
                   optionsAfterRender: $root.selectDefault">
</select>

So what optionsAfterRender really does is, on each array element it calls custom function which I've set to check if the choice is true or not and make the value of select option that which has the true.

Do note that ko.applyBindingsToNode does not work on version 2.2.0 which I had in my original fiddle.

function ViewModel(choices) {
   this.choices = ko.observableArray(choices);
    this.selectDefault = function(option,item){
        if(item.choice){
            ko.applyBindingsToNode(option.parentElement, {value: item.name}, item);
        }
    };
};
ko.applyBindings(new ViewModel(choices));

And here's the fiddle for it.

Ok If I understand you want to set the true choice as your default selected value.

First you need to involve id in your drop down so it becomes the value of the options as we will filter our collection based on that unique id

<select data-bind="options: choices, optionsText: 'name', optionsValue: 'id',  value: selectedChoice"></select>

As you see now you need to create a new observable called selectedChoice and we are going to populate that observable with the choice that is true using a computed.

var choices = [
    { id: 1, name: "one", choice: false },
    { id: 2, name: "two", choice: true },
    { id: 3, name: "three", choice: false }
    ];

function ViewModel(choices) {
   var self = this;
   self.choices = ko.observableArray(choices);
   self.trueChoice = ko.computed(function(){
       return ko.utils.arrayFirst(self.choices(), function(item){
           return item.choice === true;
       });
    });
    self.selectedChoice = ko.observable(self.trueChoice().id);
};

ko.applyBindings(new ViewModel(choices));

the new computed property trueChoice uses the arrayFirst method in order to return the first item in your choices collection that has its choice property set to true.

Now that we have our true choice all we have to do is to set the selected value of the dropdown aka selectedChoice to be the id of that true choice so the item becomes selected in the drop down.

Here is also a working fiddle for this

Added a Gist that disabled the first option in a select drop down list, and work nicely with KO's optionsCaption binding, using a optionsDisableDefault binding:

https://gist.github.com/garrypas/d2e72a54162787aca345e9ce35713f1f

HTML:

<select data-bind="value: MyValueField,
    options:OptionsList,
    optionsText: 'name',
    optionsValue: 'value',
    optionsCaption: 'Select an option',
    optionsDisableDefault: true">
</select>

You could create a computed that holds the selected items

self.selected_options = ko.computed({
    read: function() {
        return self.choices.filter(function(item){ return item.choice });
    },
    write: function(value) {
        self.choices.forEach(function(item) { item.choice = value.indexOf(item) > 0;});
    }
})

Then bind to that as the selected options.

发布评论

评论列表(0)

  1. 暂无评论