无法获得optionsValue以使用依赖下拉列表和Knockout映射插件

时间:2017-07-24 23:44:10

标签: javascript knockout.js knockout-mapping-plugin

我是一名数据库开发人员( 问题),其任务是发出与Knockout.js一起使用的JSON来呈现依赖列表项的集合。我刚刚开始使用Knockout,所以这很可能是我遗漏的事情。

这是标记:

<select data-bind="options:data,
                   optionsText:'leadTime',
                   value:leadTimes">
</select>

<!--ko with: leadTimes -->
    <select data-bind="options:colors,
                       optionsText:'name',
                       optionsValue:'key',
                       value:$root.colorsByLeadTime">
    </select>
<!--/ko-->

以下是测试数据和代码:

var data = [
    {
        key:"1",
        leadTime:"Standard",
        colors:[
            { key:"11", name:"Red" },
            { key:"12", name:"Orange" },
            { key:"13", name:"Yellow" }
        ]
    },
    {
        key:"2",
        leadTime:"Quick",
        colors:[
            { key:"21", name:"Black" },
            { key:"22", name:"White" }
        ]
    }
]

var dataViewModel = ko.mapping.fromJS(data);

var mainViewModel = {
    data:dataViewModel,
    leadTimes:ko.observable(),
    colorsByLeadTime:ko.observable()
}

ko.applyBindings(mainViewModel); 

这样,它正确填充了第二个选择列表的value属性。但是,如果我将optionsValue:'key'添加到第一个选择列表,则会正确设置value属性,但第二个选择列表会显示为空列表。

我需要的是将value标记的option属性设置为数据中提供的key值,而不管选择列表在依赖列表。我看了很多文章和文档,但是这个特殊的场景(我认为很常见)让我望而却步。

这是一个包含上面给出的数据,JS和标记的jsfiddle:http://jsfiddle.net/tnagle/Lyxjt11y/

1 个答案:

答案 0 :(得分:0)

要真正看到问题,您可以在mainViewModel初始化后添加以下代码。

mainViewModel.leadTimes.subscribe(function(newValue) { 
  console.log(newValue);
  debugger; 
});

在添加optionsValue:'key'之前,上面的行会记录以下输出。

Object {key: function, leadTime: function, colors: function}

但是在添加optionsValue:'key'之后,它会记录以下输出。

"1"

"2"

失败的原因是因为当你将optionsValue: 'key'分配给第一个选择列表时,你的mainViewModel的leadTimes属性将包含一个具有属性颜色的对象,现在将被设置为一个字符串宾语。然后,选择列表无法从color找到已更改为字符串对象的leadTimes属性。

使其发挥作用的一种方法是改为:

var data = [
  {
    key:"1",
    leadTime:"Standard",
    colors:[
      { key:"11", name:"Red" },
      { key:"12", name:"Orange" },
      { key:"13", name:"Yellow" }
    ]
  },
  {
    key:"2",
    leadTime:"Quick",
    colors:[
      { key:"21", name:"Black" },
      { key:"22", name:"White" }
    ]
  }
]

var dataViewModel = ko.mapping.fromJS(data);

var mainViewModel = new function (){
  var self = this;
  self.data = dataViewModel;
  self.leadTimes = ko.observable();
  self.selectedKey = ko.observable();
  self.selectedKey.subscribe(function(selectedKey){
	self.selectedData(ko.utils.arrayFirst(self.data(), function(item) {
        return item.key() == selectedKey;
    }));
  }, self); 
  self.colorsByLeadTime = ko.observable();
  self.selectedData = ko.observable();
}

ko.applyBindings(mainViewModel);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>    

<select data-bind="options:data,
               optionsText:'leadTime',
               optionsValue:'key',
               value:selectedKey">
</select>   
  
<!--ko with: selectedData -->
<select data-bind="options:colors,
                   optionsText:'name',
                   optionsValue:'key',
                   value:$root.colorsByLeadTime">
</select>
<!--/ko-->