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.
4 Answers
Reset to default 10I 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.
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:16choice === true
and put it in yourselectedOption
observable. As it currently stands, it's not going to work becausechoice
isn't an observable anyway and you have the problem that you can't changechoice
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