javascript - knockout 链接选择选项

标签 javascript html knockout.js

我正在开始机智 knockout ,我正在尝试创建一个链接 <select>很像 通常的国家/地区选择器,当您选择一个国家/地区时,州列表会更新为仅显示所选国家/地区的州。

我设法让它几乎按照我想要的方式工作,但问题仍然存在。

我的 friend :

var AppViewModel = function () {
        var self = this;


        self.categories = [{ Name: "A", Sub: [{ Name: "A1" }, { Name: "A2" }] }, { Name: "B", Sub: [] }];


        // the one we are working with.
        self.currentCategory = ko.observable(self.categories[0]);
        self.currentSubcategory = ko.observable();

    };

我的html:

<select data-bind="options: categories,
optionsText: 'Name',
value: currentCategory"></select>

<select data-bind="options: currentCategory().Subcategories,
optionsText: 'Name',
value: currentSubcategory"></select>

如果全部categories,这效果很好。有Sub属性(property)已填充。 但是,如果Sub如果为空,如B从上面的示例中,当我选择它时,我在控制台中收到错误:Cannot read property 'Name' of undefined ,因为currentCategory().Subcategories B 将是一个空数组.

我的问题是:我该如何解决这个问题?我预计 knockout 不会尝试渲染任何内容,因为 B.Subcategories是空的...很奇怪:为什么它不渲染一个空的?

类似问题:

如果我想使用optionsCaption ,那么根据我的理解,我的值不能是一个复杂的对象,因为标题是一个字符串。

所以如果我修改html:

<select data-bind="options: categories,
optionsCaption: 'Select a category',
optionsText: 'Name',
optionsValue: 'Id',
value: currentCategory"></select>

<select data-bind="options: categories[currentCategory].Subcategories,
optionsCaption: 'Select a subcategory',
optionsText: 'Name',
optionsValue: 'Id',
value: currentSubcategory"></select>

我也会遇到同样的问题,因为当 optionsCaption已选择,currentCategory不是 categories 的有效索引数组。

这是一个我的代码几乎可以工作的 fiddle ,除了当我选择 B 时,第二个列表不会更新为空,直到我手动选择它。 https://jsfiddle.net/byxL373j/1/

        var AppViewModel = function () {
            var self = this;


            self.categories = [{ Name: "A", Sub: [{ Name: "A1" }, { Name: "A2" }] }, { Name: "B", Sub: [] }];


            // the one we are working with.
            self.currentCategory = ko.observable();
            self.currentSubcategory = ko.observable();

        };

        var viewModel = new AppViewModel();
        ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <select data-bind="options: categories,
    optionsText: 'Name',
    value: currentCategory"></select>

    <select data-bind="foreach: currentCategory().Sub,
    value: currentSubcategory">

        <option data-bind="text: Name, value: $data"></option>

    </select>

最佳答案

在您的第一个问题中,您没有在任何地方定义currentCategory().Subcategories,那么它总是会显示错误。请改用currentCategory().Sub。然后您可以在第二次选择时使用可见绑定(bind):

        var AppViewModel = function() {
          var self = this;


          self.categories = [{
            Name: "A",
            Sub: [{
              Name: "A1"
            }, {
              Name: "A2"
            }]
          }, {
            Name: "B",
            Sub: []
          }];


          // the one we are working with.
          self.currentCategory = ko.observable();
          self.currentSubcategory = ko.observable();

        };

        var viewModel = new AppViewModel();
        ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: categories,
    optionsText: 'Name',
    value: currentCategory"></select>


<select data-bind="options: currentCategory().Sub,
    value: currentSubcategory,
    optionsText: 'Name',
    visible: currentCategory().Sub.length > 0">
</select>

如果您想显示类别帮助文本,您可以执行以下操作。请注意虚拟 if 绑定(bind) - 它甚至不会尝试查看注释内的代码,除非您的类别首先被选择。这就是使它不会中断/给出控制台错误的原因。

var AppViewModel = function() {
  var self = this;


  self.categories = [{
    Name: "A",
    Sub: [{
      Name: "A1"
    }, {
      Name: "A2"
    }]
  }, {
    Name: "B",
    Sub: []
  }];


  // the one we are working with.
  self.currentCategory = ko.observable();
  self.currentSubcategory = ko.observable();

};

var viewModel = new AppViewModel();
ko.applyBindings(viewModel);
p {
  margin: 0;
}
hr {
  margin: 22px 0;
}
hr + p {
  margin-bottom: 11px;
  font-size: 11px;
}
span {
  font-weight: bold;
  color: purple;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: categories,
    optionsCaption: 'Select a category',
    optionsText: 'Name',
    value: currentCategory"></select>

<!-- ko if: currentCategory -->
<select data-bind="options: currentCategory().Sub,
    value: currentSubcategory,
    optionsCaption: 'Select a subcategory',
    optionsText: 'Name',
    visible: currentCategory().Sub.length > 0">
</select>
<!-- /ko -->


<hr>
<p>debug:</p>
<p>Selected category:
  <span data-bind="if: currentCategory"> 
    <span data-bind="text: currentCategory().Name"></span></span>
  <span data-bind="if: !currentCategory()">none</span>
</p>
<p>Selected subcategory:
  <span data-bind="if: currentSubcategory"> 
    <span data-bind="text: currentSubcategory().Name"></span></span>
  <span data-bind="if: !currentSubcategory()">none</span>
</p>

关于javascript - knockout 链接选择选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37638761/

相关文章:

javascript - 如何让移动浏览器保持唤醒状态

javascript - knockout 可观察数组不会更新从数组中删除元素的 View

knockout.js - 订阅后在knockoutjs中加载初始值

javascript - 未处理的拒绝错误 : WHERE parameter “number_phone” has invalid “undefined” value

javascript - 将代码库从 React 移植到 Preact-Compat,this.setState() 不是一个函数

javascript - 为什么我的 var 变得未定义但在前一个函数中设置了?

Javascript(动态)插入数组,然后将所有元素移动到+1下面

javascript - 如何在用户点击javascript时将word包装成span

javascript - jQuery onclick,选择输入框并按回车键(渲染html)

javascript - 为什么数据绑定(bind)不起作用? (使用嵌套的 foreach 循环)