Wall-E
Wall-E

Reputation: 95

Knockout.js not updating bindings in select field

I have an issue with Knockout.js . What I try to do is filter a select field. I have the following html:

    <select data-bind="options: GenreModel, optionsText: 'name', value: $root.selectedGenre"></select>
    <ul data-bind="foreach: Model">
        <span data-bind="text: $root.selectedGenre.id"></span>
        <li data-bind="text: name, visible: genre == $root.selectedGenre.id"></li>
    </ul>

And the js:

var ViewModel = function (){
    self.selectedGenre = ko.observable();
    self.Model = ko.observableArray([{
        name: "Test",
        genre: "Pop"
    }
    ]);
    self.GenreModel = ko.observableArray([
        {
        name: "Pop",
        id: "Pop"
    },

    {
        name: "Alle",
        id: "All"
    }
    ]);
};

var viewModel = new ViewModel();

ko.applyBindings(viewModel);

JSFiddle: http://jsfiddle.net/CeJA7/1/

So my problem is now that the select list does not update the binding on the span inside the ul and I don't know why...

The value binding should update the property selectedGenre whenever the select value changes, shouldn't it?

Any ideas are welcome.

Upvotes: 0

Views: 639

Answers (1)

Sergiu Paraschiv
Sergiu Paraschiv

Reputation: 10153

There are a lot of issues in your code:

1) self is not a magical variable like this. It's something people use to cope with variable scoping. Whenever you see self somewhere in a JavaScript function be sure there's a var self = this; somewhere before.

2) KnockoutJS observables are not plain variables. They are functions (selectedGenre = ko.observable()). ko.observable() returns a function. If you read the very first lines of documentation regarding observables you should understand that access to the actual value is encapsulated in this retured function. This is by design and due to limitations in what JavaScript can and cannot do as a language.

3) By definition, in HTML, <ul> elements can only contain <li> elements, not <span> or anything else.

Applying the above fixes leads to this working updated sample:

HTML:

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

<span data-bind="text: $root.selectedGenre().id"></span>

<ul data-bind="foreach: Model">      
    <li data-bind="text: name, visible: genre == $root.selectedGenre().name"></li>
</ul>

JavaScript:

var ViewModel = function (){
    var self = this;

    self.selectedGenre = ko.observable();

    self.Model = ko.observableArray([
        {
            name: "Test",
            genre: "Pop"
        }
    ]);

    self.GenreModel = ko.observableArray([
        {
        name: "Pop",
        id: "Pop"
    },

    {
        name: "Alle",
        id: "All"
    }
    ]);
};

var viewModel = new ViewModel();

ko.applyBindings(viewModel);

Upvotes: 4

Related Questions