Javascript – Multiple Select List and KnockoutJS


I have a multi-select list that I've implemented following the instructions on the KO site. The important portions of my code currently look like this (removed unnecessary code):

function Attribute(data) {
    var self = this;
    self.Id = data.Id;
    self.Name = data.Name;

// Individual Row in Table
function Criteria(data) {
    var self = this;
    self.Attributes = data.Attributes;

// Represent the ViewModel for attributes.
function CriteriaViewModel() {
    var self = this;

    // Catalog Data
    self.availableAttributes = window.ko.observableArray([]);
    $.getJSON(window.attributeListUrl, function(availableData) {
        self.availableAttributes($.map(availableData.Attributes, function(item) { return new Attribute(item); }));

    // Editable Data
    self.criterion = window.ko.observableArray([]);

    // Load initial state from server
    $.getJSON(window.criteriaListUrl, function (availableData) {
        self.criterion($.map(availableData.Criterion, function (item) { return new Criteria(item); }));

Then, in my HTML, I bind it all together (or, I at least try to):

     <tbody data-bind="foreach: criterion">
                    <select class="selectedAttributes"
                            data-bind="options: $root.availableAttributes, selectedOptions: Attributes, optionsText: 'Name', optionsValue: 'Id'"

The possible options display correctly. However, there is no apparent binding between the criteria's attributes against the possible options. From reading the guide, it seems as though KO should be able to bind objects directly. Can anybody provide guidance here?

I forgot to mention that everything works except the actual binding of the multi-select list. I am applying my bindings appropriately in general – just not with the multi-select list.

Best Solution

The attributes property on the Criteria object needs to be an observableArray. Here is a Jsfiddle demonstrating

function Criteria(data) {
    var self = this;
    self.Attributes = ko.observableArray(data.Attributes);