淘汰链接选择选项

时间:2016-06-05 05:27:42

标签: javascript html knockout.js

我开始机智淘汰赛,我试图创建一个链接<select>非常喜欢 通常的国家/地区选择器,当您选择国家/地区时,状态列表会更新以仅显示所选国家/地区的状态。

我设法让它几乎像我一样工作,但问题仍然存在。

我的k.o。:

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属性,则效果很好。 但是,如果Sub为空,如上例中的B,那么当我选择它时,我在控制台中收到错误:Cannot read property 'Name' of undefined,因为currentCategory().Subcategories将是B的空数组。

我的问题是:我该如何解决这个问题?我希望淘汰赛不会尝试渲染任何东西,因为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数组的有效索引。

这是我的代码几乎工作的小提琴,除非我选择B,第二个列表没有更新为空,直到我手动选择它。 https://jsfiddle.net/byxL373j/1/

&#13;
&#13;
        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);
&#13;
<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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

在第一期中,您没有在任何地方定义currentCategory().Subcategories,它将始终显示错误。请改用currentCategory().Sub。然后你可以在第二个选择上使用可见的绑定:

&#13;
&#13;
        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);
&#13;
<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>
&#13;
&#13;
&#13;

如果要显示类别助手文本,可以执行以下操作。注意虚拟if绑定 - 除非首先选择类别,否则它甚至不会尝试查看注释中的代码。这就是为什么它不会破坏/给出控制台错误。

&#13;
&#13;
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);
&#13;
p {
  margin: 0;
}
hr {
  margin: 22px 0;
}
hr + p {
  margin-bottom: 11px;
  font-size: 11px;
}
span {
  font-weight: bold;
  color: purple;
}
&#13;
<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>
&#13;
&#13;
&#13;