3

I have a select element where i bind the css class using Jquery Knockout.

I want to access the current element instance directly from data-bind attribute, without creating a property in the ViewModel (because i have many select elements which shares the same functionality)

Is this possible?

<select id="select1" data-bind="css: { 'no-value-selected': $item.val() == '' }">
    <option value="">[Select a value]</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>

EDIT Using ViewModel to achieve this (what i want to avoid)

function ViewModel() {
    this.select1HasNoValueSelected = ko.computed(function () {
        return $("#select1").val() == '';
    }, this);
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);

<select id="select1" data-bind="css: { 'no-value-selected': select1HasNoValueSelected }">
4
  • Not 100% sure what you're asking here, could you explain your scenario a little better? To "access the current element instance" could be done via the DOM easily? Commented Apr 16, 2013 at 8:37
  • I have added an working example in my question..hope it's more clear Commented Apr 16, 2013 at 8:45
  • This is actually a pretty difficult one, I'll continue trying to crack it. Commented Apr 16, 2013 at 9:03
  • Yes..i know:) i did some research and didn't find anything. I used plain jquery to achieve this Commented Apr 16, 2013 at 9:05

2 Answers 2

3

You are on the wrong track with the css binding because if you are not using observables it won't update your class if the value of your select is changes.

However you can (miss)use the event binding and subscribe on the change event:

<select id="select1" class="no-value-selected" data-bind="event: { 'change': 
function() { $($element).val() == '' ? 
             $($element).addClass('no-value-selected') : 
             $($element).removeClass('no-value-selected') } }">
    <option value="">[Select a value]</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>

Demo JSFiddle. (second drop-down)

But the best solution is to not fight against KnockOut and have properties for each select on your view model:

function ViewModel() {    
    this.select1Value = ko.observable()
};

<select id="select1" data-bind="css: { 'no-value-selected': !select1Value() }, 
                                value: select1Value">
    <option value="">[Select a value]</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>

Demo JSFiddle. (third drop-down)

Or don't use Kncokout for this function at all.

Sign up to request clarification or add additional context in comments.

2 Comments

That's right..i was not using observables which would not trigger css value on value change. The second solution works perfect
You could use a custom binding, if you wanted a generic solution for all your selects.
1

You can try to use $element instead of $item:

<select data-bind="css: { 'no-value-selected': $element.val() == '' }">
    <option value="">[Select a value]</option>
    <option value="1">1</option>
    <option value="2">2</option>
</select>

Docs: http://knockoutjs.com/documentation/binding-context.html

1 Comment

Nope, $element is not defined

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.