【问题标题】:knockout linked select options淘汰赛链接选择选项
【发布时间】:2016-06-05 18:19:37
【问题描述】:

我开始机智淘汰赛,我正在尝试创建一个链接的<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>

I will run into the same problem, because when the optionsCaption is selected, currentCategory is not a valid index for the categories array.

这是一个我的代码几乎可以工作的小提琴,除了当我选择 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>

【问题讨论】:

    标签: javascript html knockout.js


    【解决方案1】:

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

            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 绑定——它甚至不会尝试查看注释中的代码,除非您的类别首先被选中。这就是它不会破坏/给出控制台错误的原因。

    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>

    【讨论】:

    • 嘿@kasperoo,感谢您的回复。关于未定义的子类别,这只是一个错字,如果您检查我的小提琴和 sn-p,您会发现代码是正确的。就像你说的那样,我昨天使用了 if ,但我不太喜欢这个解决方案,因为我可能想显示第二个选择,即使它是空的。我不知道可见的绑定,很酷。运行我的sn-p,看到第二个select在选择B的时候没有更新为空。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 2013-07-15
    • 2017-12-07
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多