Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set an <option> element's class attribute via KnockoutJS

Tags:

knockout.js

I have HTML select element being populated via a KnockoutJS viewmodel like so:

<select data-bind="options: $data.answers,  optionsText: function(item) { return item.text }, value: selectedAnswer, optionsCaption: 'Choose...'"></select>

What I would like to do is set the class attribute of each option element by some means, so that I end up with:

<option class="someValue">12345</option>

Can this be done in KnockoutJS? I'm having difficulty in finding a solution for this.

EDIT:

I've just tried the foreach binding, as suggested by Artem and it is very close to working as I want. But there is one issue.

On the Question object there is a function which subscribes to the SelectedAnswer observable:

this.selectedAnswer.subscribe(function (answer) {}

When I use the foreach binding, the subscribe() fires off, once for each question (it shouldn't fire until I've chosen an answer. I think this is because the "Choose..." option is now not shown).

For the foreach binding, how can I set the default text back to "Choose..." and stop the selectedAnswer.subscribe() from firing until the user has chosen an item, and not when the list is being populated.

EDIT:

OK here's how I've done this.

In the KO viewmodel class I have a boolean bindingFinished which I check inside of selectedAnswer.subscribe(). If false then we just return from the function; if true then carry on as normal.

Also I add a default "Choose" option to the answers by adding a new Answer to the beginning of the array. The end result is that the subscribe function is not executed when the data is being bound, only after the user has chosen an option.

Many thanks to Artem for your help.

like image 502
Jason Evans Avatar asked Dec 26 '22 14:12

Jason Evans


2 Answers

You can do this with the optionsAfterRender binding.
It will invoke the provided function for each option element it generated.
All you have to do is add the class to the element.

Example:

HTML:

<select class="form-control" data-bind="options: list, 
        optionsAfterRender: addOptionClass"></select>

JS:

this.addOptionClass = function(optionElement) {
    optionElement.classList.add("form-control");
};
like image 175
Domysee Avatar answered Mar 08 '23 08:03

Domysee


You can use foreach binding instead of options in the select tag:

<select data-bind="value: selectedAnswer">
    <option class="someValue">Choose...</option>
    <!-- ko foreach: $data.answers -->
    <option class="someValue" data-bind="value: $data, text: text"></option>
    <!-- /ko -->
</select>

Here is working fiddle: http://jsfiddle.net/vyshniakov/5bPWQ/1/

like image 22
Artem Vyshniakov Avatar answered Mar 08 '23 07:03

Artem Vyshniakov