Is it possible to alter the styling (using 'style' or 'css' binding) of a select list's option element when using the 'options' binding on a select list? Or can this only be done by using a 'foreach' on the select list and altering the styling for each ?
I have this in code:
<select id="ponents-select" size="4" name="ponents-select"
data-bind=" options: binedComponents,
optionsText: 'displayName',
optionsValue: 'id',
value: chosenComponent"></select>
but if I append style: {color: isDefault() === true ? 'black' : 'red'}
then the entire list is coloured Red if isDefault
returns false.
Is the only way to achieve this to code it this way:
<select id="ponents-select" size="4" name="ponents-select"
data-bind="foreach: binedComponents">
<option data-bind="value: id, text: displayName, style: {color: isDefault() === true ? 'black' : 'red'}"></option>
</select>
Or is there some form of Knockout.js wizardry that I am not aware of?
Thanks!
Is it possible to alter the styling (using 'style' or 'css' binding) of a select list's option element when using the 'options' binding on a select list? Or can this only be done by using a 'foreach' on the select list and altering the styling for each ?
I have this in code:
<select id="ponents-select" size="4" name="ponents-select"
data-bind=" options: binedComponents,
optionsText: 'displayName',
optionsValue: 'id',
value: chosenComponent"></select>
but if I append style: {color: isDefault() === true ? 'black' : 'red'}
then the entire list is coloured Red if isDefault
returns false.
Is the only way to achieve this to code it this way:
<select id="ponents-select" size="4" name="ponents-select"
data-bind="foreach: binedComponents">
<option data-bind="value: id, text: displayName, style: {color: isDefault() === true ? 'black' : 'red'}"></option>
</select>
Or is there some form of Knockout.js wizardry that I am not aware of?
Thanks!
Share Improve this question edited Mar 27, 2019 at 15:28 rwcorbett asked Apr 11, 2013 at 19:01 rwcorbettrwcorbett 4735 silver badges12 bronze badges 4-
There aren't any wizardry options out there that I'm aware of. The default
options
binding handler only emits what is absolutely necessary the get the required semantics. And setting the color of each of the options was not a configurable setting. You could rewrite the handler to add those options. Possibly set the styles after the controls are rendered? – Jeff Mercado Commented Apr 11, 2013 at 19:10 -
1
No there is no direct support for this in the KO
options
binding. But I think your second example with the manualforeach
is the simplest solution for this problem. – nemesv Commented Apr 11, 2013 at 19:17 -
If you're going to be doing anything like this more than just this one time, you're better off creating your own binding handler, using
options
as a guide, e.g.optionsWithColor
– Chris Pratt Commented Apr 11, 2013 at 21:39 - 1 For anyone looking for this option, check out this question - stackoverflow./questions/25491607/… – Nick Commented Sep 24, 2014 at 13:03
4 Answers
Reset to default 2To expand on Thomas Wiersema's answer, the way you'd want to approach handling that on a per-row basis is something like:
<select id="ponents-select" size="4" name="ponents-select"
data-bind="foreach: binedComponents">
<option data-bind="value: id, text: displayName, style: {color: getColorFor.call(null, $data) }"></option>
</select>
then, in JavaScript, attach a function to your parent object like so (I'm making some assumptions, of course, like your parent object being called vm
and isDefault
belonging to a binedComponent):
vm.getColorFor = function(ponent) {
return ponent.isDefault() === true ? 'black' : 'red';
}
If you're not sure what call
does, check out bind vs apply vs call
I hope that helps -- let me know if I can elaborate!
To answer your question, yes that is the best way I believe.
with the code style: {color: isDefault() === true ? 'black' : 'red'}
you bind(add) a style to the associated DOM element. In this case the whole <select>
tag. Not a <option>
tag like you want. That's why your entire list changes color.
Take a look at the knockoutjs docs for more info about style binding.
Try the 'optionsAfterRender' Binding which in this case works fine. http://jsfiddle/cZRJN/243/
var viewModel = function() {
this.binedComponents = ko.observableArray([{
displayName: 'item1',
id: 1,
isDefault:true
}, {
displayName: 'item2',
id: 2,
isDefault:false
}, {
displayName: 'item3',
id: 3,
isDefault:true
}]);
OptionsAfterRender = (option, item) => {
ko.applyBindingsToNode(option, {style: { color: item.isDefault ? 'red' : 'black'}}, item);
};
this.chosenComponent= ko.observable(1);
}
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare./ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<select id="ponents-select" size="4" name="ponents-select"
data-bind=" options: binedComponents,
optionsText: 'displayName',
optionsValue: 'id',
value: chosenComponent,
optionsAfterRender:OptionsAfterRender
"></select>
To add up the what has already been said, there is one feature of Knockout that I find get's overlooked a lot and is very handy in these situations: $index
. For example, I am making a list where I want the first option in the list to be black and the rest to be red. So I can just modify what you have as your second option like so:
<select id="ponents-select" size="4" name="ponents-select"
data-bind="foreach: binedComponents">
<option data-bind="value: id, text: displayName,
style: {color: $index === 0 ? 'black' : 'red'}"></option>
</select>
Or if you want to alternate colors just use a modulus check.
<select id="ponents-select" size="4" name="ponents-select"
data-bind="foreach: binedComponents">
<option data-bind="value: id, text: displayName,
style: {color: $index % 2 === 1 ? 'black' : 'red'}"></option>
</select>