Knockout.js - Lost two way binding of select value when using foreach instead of option


List

I have two select controls.

One depends on the other. As a simple example, let's say the first displays a list of cities and the other displays a list of streets for each city.

When the page is initially loaded, the display street selection control will display all available streets. However, once the user selects a city in the first selection, the second selection is filtered to display only streets that belong to the selected city.

This works fine when using option binding, however, I need to have the ability to generate optgroup and option binding doesn't support it, so I have to use foreach binding.

As a result, just picking a city has two unintended consequences:

  1. Even if I use valueAllowUnset: true the second selection (filtered list of streets) seems to have the first street of the selected city. This is not reflected in the view model
  2. When actually selecting a street in the 2nd selection and then a different city in the 1st selection, the 2nd selection correctly updates to reflect the change in the list, but the viewmodel does not update so the previously selected value is still retained (even if it's no longer in the list). The problem persists even after removing valueAllowUnset: true from the second select.

Is there a solution to this problem? I really have to use foreach binding instead of option binding.

JSFiddle:https://jsfiddle.net/jfxovLna/13/

var ViewModel = function() {

var self = this;

var regionAndCityArray = [{
 regionName: "Europe",
 cities: [{
   cityName: "London",
   additionalUnimportantInformation: 100
 }, {
   cityName: "Paris",
   additionalUnimportantInformation: 200
 }]
}, {
 regionName: "North America",
 cities: [{
   cityName: "New York",
   additionalUnimportantInformation: 45
 }]
}];

var cityAndStreetArray = [{
 cityName: "London",
 streets: [{
   streetName: "Parker",
   streetLength: 5
 }, {
   streetName: "Macklin",
   streetLength: 10
 }, ]
}, {
  cityName: "New York",
 streets: [{
   streetName: "5th Avenue",
   streetLength: 3
 }, {
   streetName: "Park Ave",
   streetLength: 12
 }]
}, {
  cityName: "Paris",
 streets: [{
   streetName: "Rue de Turbigo",
   streetLength: 11
 }, {
   streetName: "Rue aux Ours",
   streetLength: 12
 }]
}];

var getAvailableStreets = function() {

 var availableStreets = cityAndStreetArray;

 var selectedCity = self.selectedCity();

 var selectedRegion = _.find(regionAndCityArray,
   function(region) {
     return _.find(region.cities,
       function(city) {
         return city.cityName === selectedCity;
       });
   });

 if (selectedRegion == undefined) {
   return availableStreets;
 }

 var filteredStreets = _.filter(cityAndStreetArray,
   function(city) {
     return city.cityName === selectedCity;
   });

 return filteredStreets;
}

self.availableCities = ko.observableArray(regionAndCityArray);
self.selectedCity = ko.observable();
self.availbleStreets = ko.computed(getAvailableStreets);
self.selectedStreet = ko.observable();

};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
Cookie Monster

First, add an empty option to the selected input.

<option value="">Select Street</option>

Now, subscribe to the selectedCity property of your view model. You can programmatically set selectedStreet to "" whenever you change it.

viewModel.selectedCity.subscribe(function() { 
  viewModel.selectedStreet(''); 
}, viewModel); 

In this way, you can solve two problems.

Made changes in your fiddle and it works fine. try to update it.

Here is a fiddle - https://jsfiddle.net/Shabi_669/w1vcjbjo/

Related


Knockout binding not updating with foreach select option

Yono I have two options, the second option depends on the first option. Both select boxes need to have a class attached, so I can't use the options property. The only way I've found to do this is to use the foreach method. I need to keep track of two selected

Knockout binding not updating with foreach select option

Yono I have two options, the second option depends on the first option. Both select boxes need to have a class attached, so I can't use the options property. The only way I've found to do this is to use the foreach method. I need to keep track of two selected

Blazor two-way binding <select>/<option>

maddyhatty23 I'm having trouble trying to update a list option in a selection. When the Function Onebutton is clicked, it triggers functionTwoit to return a new list, which should now display the updated list<select>/<option> Can someone educate me on what I'm

knockout select option text foreach

Evan Stark I have an object that contains a list of schools with nested classes and nested students in each class What I need is to bind the optionsText to show the hierarchy so that the dropdown menu shows the options, like: A school has student 1 student 2 S

Default Angular2 <option> in <select> using two-way binding

mariocatch: I want to set <select>default values using HTML <option>and <select>bind to the rest of the model using two ways . HTML: <select class="form-control" required [(ngModel)]="model.product" ngControl="product"> <option value="">Sel

Default Angular2 <option> in <select> using two-way binding

mariocatch: I want to set <select>default values using HTML <option>and <select>bind to the rest of the model using two ways . HTML: <select class="form-control" required [(ngModel)]="model.product" ngControl="product"> <option value="">Sel

Default Angular2 <option> in <select> using two-way binding

mariocatch: I want to set <select>default values using HTML <option>and <select>bind to the rest of the model using two ways . HTML: <select class="form-control" required [(ngModel)]="model.product" ngControl="product"> <option value="">Sel

Knockout.js foreach binding works but not binding

Gera Plant Using Knockout.js 3.2.0, I've been struggling to get the observableArray to bind successfully and narrow it down to the with binding. The foreach has no problem, but with throws the error Uncaught ReferenceError: cannot handle combining 'with: funct

Knockout.js foreach binding works but not binding

Gera Plant Using Knockout.js 3.2.0, I've been struggling to get the observableArray to bind successfully and narrow it down to the with binding. The foreach has no problem, but with throws the error Uncaught ReferenceError: cannot handle combining 'with: funct

Angular2 two way binding to select option not updating

Nemir I have a select list bound to the Person property on a component using [ngValue]. When I change the selection, the selectedPerson property of the underlying style is updated as expected. However, the selection does not default to the selected person on i

Angular2 two way binding to select option not updating

Nemir I have a select list bound to the Person property on a component using [ngValue]. When I change the selection, the selectedPerson property of the underlying style is updated as expected. However, the selection does not default to the selected person on i

Angular2 two way binding to select option not updating

Nemir I have a select list bound to the Person property on a component using [ngValue]. When I change the selection, the selectedPerson property of the underlying style is updated as expected. However, the selection does not default to the selected person on i

Default Angular2 <option> in <select> with two-way binding

fishing I want to set <select>default values using HTML <option>and <select>bind to the rest of the model using two ways . HTML: <select class="form-control" required [(ngModel)]="model.product" ngControl="product"> <option value="">Select

Angular2 two way binding to select option not updating

Nemir I have a select list bound to the Person property on a component using [ngValue]. When I change the selection, the selectedPerson property of the underlying style is updated as expected. However, the selection does not default to the selected person on i

Angular2 two way binding to select option not updating

Nemir I have a select list bound to the Person property on a component using [ngValue]. When I change the selection, the selectedPerson property of the underlying style is updated as expected. However, the selection does not default to the selected person on i

How to apply binding and persist input value using Knockout JS?

Kees C. Bakker I am building an HTML/KnockoutJS application. My web server returns a form with input fields and information. When I update the model and execute ko.applyBindings, the input value is naturally overwritten by the model. Is there a way to automati

How to apply binding and persist input value using Knockout JS?

Kees C. Bakker I am building an HTML/KnockoutJS application. My web server returns a form with input fields and information. When I update the model and execute ko.applyBindings, the input value is naturally overwritten by the model. Is there a way to automati

How to apply binding and persist input value using Knockout JS?

Kees C. Bakker I am building an HTML/KnockoutJS application. My web server returns a form with input fields and information. When I update the model and execute ko.applyBindings, the input value is naturally overwritten by the model. Is there a way to automati

Knockout JS binding doesn't output value using simple viewmodel

Carl Weiss I'm trying to load a simple view model that has two models: Profile (a ko.observable()) and Request (a ko.observableArray()). When I apply the binding and then try to bind to the ether profile.field or foreach: request, I get no output, no javascrip