Knockoutjs - 在使用 foreach 而不是选项时丢失了绑定到 select 值的两种方式

Knockoutjs - lost two way binding to select value when using foreach instead of options

我有两个 select 控件。

一个依赖另一个。举个简单的例子,假设第一个显示城市列表,而另一个显示每个城市的街道列表。

最初加载页面时,显示街道的 select 控件会显示所有可用的街道。但是,一旦用户在第一个 select 中选择了一个城市,第二个 select 将被过滤以仅显示属于 selected 城市的街道。

这在使用选项绑定时工作正常,但是,我需要生成 optgroups 的能力,而选项绑定不支持它,所以我必须使用 foreach 绑定。

结果是,每当城市被 selected 时,都会发生两个意想不到的后果:

  1. 第二个 select(过滤后的街道列表)似乎选择了 selected 城市的第一条街道,即使我使用的是 valueAllowUnset: true。 这没有反映在视图模型中
  2. 当实际在第二个 select 中选择一条街道,然后在第一个 select 中选择不同的城市时,第二个 select 会正确更新以反映列表中的更改,但是视图模型没有,因此仍然保留以前的 selected 值(即使它不再在列表中)。即使我从第二个 select 中删除 valueAllowUnset: true,问题仍然存在。

这个问题有解决办法吗?我真的必须使用 foreach 绑定而不是选项绑定。

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);

首先,向您的 select 输入添加一个空选项。

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

现在订阅您的视图模型的 selectedCity 属性。 每当它发生变化时,以编程方式将 selectedStreet 设置为 ''.

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

这样你就可以解决两个问题了。

在您的 fiddle 中进行了更改并且它起作用了。尝试更新它。

这是一个fiddle - https://jsfiddle.net/Shabi_669/w1vcjbjo/