我开始机智淘汰赛,我试图创建一个链接<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/
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;
答案 0 :(得分: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);
&#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;
如果要显示类别助手文本,可以执行以下操作。注意虚拟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);
&#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;