Knockout下拉级联选项不更新

时间:2016-07-20 01:10:33

标签: ajax knockout.js

我正在尝试使用knockout填充依赖下拉列表的默认值。

当值被编码时,它可以工作,但我需要从ajax请求中获取值,然后,第二个下拉选项不会更新。值self.selectedState已更新,但我想因为我还没有填充选项,所以select中的值不是bind。到目前为止,这是我的代码:

function myViewModel(country, state) {
	var self = this;
  self.selectedCountry = ko.observable();
	self.selectedState = ko.observable();
  
  self.availableCountries = ko.observableArray([
  	{
  		id: 1, name: 'United States', states: [
				{ id: 1, name: 'Alabama' },
        { id: 2, name: 'California' },
			]
		},
		{
			id: 2, name: 'Canada', states: [
				{ id: 53, name: 'Alberta' },
			]
		}
	]);
  
  self.availableStates = ko.observableArray([]);
	
  self.selectedCountry.subscribe(function() {
		self.availableStates([]);
  
		for (var i = 0; i < self.availableCountries().length; i++) {
			if (self.availableCountries()[i].id == self.selectedCountry()) {
				self.availableStates(self.availableCountries()[i].states);
				break;
			}
		}
	});
  
  self.selectedCountry(1).selectedState(2);
}

var viewModel = new myViewModel();
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: availableCountries, optionsText: 'name', optionsValue: 'id', optionsCaption: 'Select a country...',
value: selectedCountry"></select>

<select data-bind="options: availableStates, optionsText: 'name',optionsValue: 'id', value: selectedState, visible: availableStates().length > 0" style="display:none"></select>

当从ajax获取选项时,是否需要做一些特殊的事情?

jsfiddle

2 个答案:

答案 0 :(得分:1)

问题不在于AJAX,尤其是self.selectedState在一段时间内没有相应的option这一事实(在提取选项时)。 来自the docs

  

通常,当您在value元素上使用<select>绑定时,它就是   表示您希望关联的模型值描述哪个项目   已选中<select>。但是如果你设置模型会发生什么   值列表中没有相应条目的东西?该   默认行为是Knockout将模型值覆盖为   将其重置为下拉列表中已选择的任何内容   防止模型和UI失去同步。

     

但是,有时您可能不希望出现这种行为。如果相反你   想要Knockout允许你的模型可观察到具有的值   <select>中没有相应的条目,然后指定valueAllowUnset: true。在这种情况下,只要您的模型值无法表示   <select><select>根本没有选定的值   时间,在视觉上由空白表示。

答案 1 :(得分:0)

这是一个利用计算可观察量的绝佳机会。计算似乎非常适合这项工作,因为它可以帮助您避免在跟踪依赖项中设置自己的手动订阅。尝试一下 - 我已经改变了非常你的代码来实现这一目标。

&#13;
&#13;
function myViewModel(country, state) {
  var self = this;
  self.selectedCountry = ko.observable();
  self.selectedState = ko.observable();

  self.availableCountries = ko.observableArray([{
    id: 1,
    name: 'United States',
    states: [{ id: 1, name: 'Alabama' }, 
             { id: 2, name: 'California' }, ] 
    }, 
    { id: 2, 
      name: 'Canada',
      states: [{ id: 53, name: 'Alberta' }, ]
  }]);

  self.availableStates = ko.computed(function() {
    var states = [];
    for (var i = 0; i < self.availableCountries().length; i++) {
      if (self.availableCountries()[i].id == self.selectedCountry()) {
        states = states.concat(self.availableCountries()[i].states);
        break;
      }
    }
    return states;
  });

  self.selectedCountry(1).selectedState(2);
}

var viewModel = new myViewModel();
ko.applyBindings(viewModel);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: availableCountries, optionsText: 'name', optionsValue: 'id', optionsCaption: 'Select a country...',
value: selectedCountry"></select>

<select data-bind="options: availableStates, optionsText: 'name',optionsValue: 'id', value: selectedState, visible: availableStates().length > 0" style="display:none"></select>
&#13;
&#13;
&#13;