Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockoutjs <select> based on another <select> not working

I am trying to activate two select fields with options having values, eg. <option value='...'>...</option> using Knockoutjs.

And it populates second select field options with values based on the selected value in the first select field.

FYI, I found http://knockoutjs.com/examples/cartEditor.html, but this does not use optionsValue either so it was not helpful.

Here's my view:

<select data-bind="options: list,
                   optionsCaption: 'Select...',
                   optionsText: 'location',
                   optionsValue: 'code',
                   value: selectedRegion">                 
</select>
<!-- ko with : selectedRegion -->
<select data-bind="options: countries,
                   optionsCaption: 'Select...',
                   optionsText: 'location',
                   optionsValue: 'code',
                   value: $parent.selectedCountry">
</select>
<!-- /ko  -->

Here's my view:

var packageData = [
    {
        code : "EU",
        location: 'Euprope',
        countries : [
            { location: "England", code: 'EN' },
            { location: "France", code: 'FR' }
        ]
    },
    {
        code : "AS",
        location: 'Asia',
        countries : [
            { location: "Korea", code: 'KO' },
            { location: "Japan", code: 'JP' },
        ]
    }
];

function viewModel(list, addons) {
    this.list = list;
    this.selectedRegion = ko.observable();
    this.selectedCountry = ko.observable();
}

ko.applyBindings(new viewModel(packageData)); 

If run above, I get the following JS error.

Uncaught ReferenceError: Unable to parse bindings.
Bindings value: options: countries,
                   optionsCaption: 'Select...',
                   optionsText: 'location',
                   optionsValue: 'code',
                   value: $parent.selectedCountry
Message: countries is not defined

Above works if I lose 'optionsValue: 'code,' lines in my view (one for first select field, another for second select field. However this does not populate the option values and this is not what I want.

For example, <option value>...</option> instead of <option value="[country code]">...</option>.

Can someone please help how I can fix my code so I get <option value="[country code]">...<option>?

Thanks so much in advance.

like image 761
user2975436 Avatar asked Jun 21 '26 06:06

user2975436


1 Answers

The problem is that when you set the optionsValue property selectedRegion is now populated with only the code. The code property does not have a countries property underneath and so the binding fails. One way to work around this is to use a computed observable the returns the countries based on the selectedRegion code.

self.countryList = ko.computed(function () {
    var region = self.selectedRegion();
    var filtered = ko.utils.arrayFirst(self.list, function (item) {
        return item.code == region;
    });
    if (!filtered) {
        return []
    } else {
        return filtered.countries;
    }
});

Then you just change the binding to use the computed: options: $root.countryList.

Working example: http://jsfiddle.net/infiniteloops/AF2ct/

like image 59
Gary.S Avatar answered Jun 23 '26 04:06

Gary.S



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!