是否有更短/更清晰的方法来进行null / undefined测试?
<select data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [],
optionsText: 'Title',
value: SelectedCluster,
optionsCaption: 'Select Cluster..'">
</select>
而不是
data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [],
我想要
data-bind="options: SelectedBusinessLine().Clusters(),
给予或接受()
或至少一个更简单的空操作符检查'??' SelectedBusinessLine ?? []
或者自动检查null或silent失败的绑定参数。
如果有可能,有什么想法吗?
答案 0 :(得分:74)
This page提供了多种解决方案。相关部分是这一个:
防止空对象
如果你有一个包含一个对象的observable并且想要绑定到该对象的属性,那么如果它有可能为null或未定义,则需要小心。你可以写下你的装订:
<span data-bind="text: selectedItem() ? selectedItem().name() : 'unknown'"></span>
有很多方法可以处理这个问题。首选方法是简单地使用模板绑定:
var viewModel = {
items: ko.observableArray(),
selectedItem: ko.observable()
};
<ul data-bind="template: { name: 'editorTmpl', data: selectedItem }"></ul>
<script id="editorTmpl" type="text/html">
<li>
<input data-bind="value: name" />
</li>
</script>
使用此方法,如果selectedItem
为null,则它不会呈现任何内容。所以,你不会看到原始绑定中的未知。但是,它确实具有简化绑定的附加好处,因为您现在可以直接指定属性名称而不是selectedItem().name
。这是最简单的解决方案。
仅仅为了探索一些选择,这里有一些选择:
你可以使用计算的observable,就像我们之前做的那样。
viewModel.selectedItemName = ko.computed(function() {
var selected = this.selected();
return selected ? selected.name() : 'unknown';
}, viewModel);
然而,这再次为我们可能不想要的视图模型增加了一些膨胀,我们可能不得不为许多属性重复这个。
您可以使用自定义绑定,如:
<div data-bind="safeText: { value: selectedItem, property: 'name', default: 'unknown' }"></div>
ko.bindingHandlers.safeText = {
update: function(element, valueAccessor, allBindingsAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()),
value = ko.utils.unwrapObservable(options.value),
property = ko.utils.unwrapObservable(options.property),
fallback = ko.utils.unwrapObservable(options.default) || "",
text;
text = value ? (options.property ? value[property] : value) : fallback;
ko.bindingHandlers.text.update(element, function() { return text; });
}
};
这比原来好吗?我想说可能不是。它确实避免了我们绑定中的JavaScript,但它仍然非常冗长。
另一个选项是创建一个增强的observable,它提供了一种访问属性的安全方法,同时仍允许实际值为null。可能看起来像:
ko.safeObservable = function(initialValue) {
var result = ko.observable(initialValue);
result.safe = ko.dependentObservable(function() {
return result() || {};
});
return result;
};
所以,这只是一个observable,它还公开了一个计算的observable,它将始终返回一个空对象,但是实际的observable可以继续存储null。
现在,你可以绑定它:
<div data-bind="text: selectedItem.safe().name"></div>
当它为null时,你不会看到未知值,但是当selectedItem
为空时,它至少不会导致错误。
我确实认为首选的选项是在这种情况下使用模板绑定,特别是如果您要绑定许多这些属性。
答案 1 :(得分:59)
另一个答案引用的otherwise excellent page中未提及的一种方法是使用with
<div data-bind="with: selecteditem">
<form>
<fieldset>
<div>
<label>first name</label>
<input data-bind="value: firstname"></input>
</div>
<div>
<label>lasst name</label>
<input data-bind="value: lastname"></input>
</div>
</fieldset>
<div>
<a href="#" data-bind="click: $root.savechanges">Save</a>
</div>
</form>
</div>
如果selecteditem
为空,则整个UI都将消失。
答案 2 :(得分:4)
“With”作品(可能其他作品也是......)
但是使用“With”,即使内部存在条件,UI也会消失/出现...例如......我需要设置状态(true / false)按钮,但仅当状态不是空...
<!-- ko ifnot: Status() == null -->
<span data-bind="if: Status">
<a class="rk-button rk-red-action" data-bind="click: changeStatus"><i class="rk-ico rk-ico-save"></i>Desativar</a>
</span>
<span data-bind="ifnot: Status">
<a class="rk-button rk-black-action" data-bind="click: changeStatus"><i class="rk-ico rk-ico-save"></i>Ativar</a>
</span>
<!-- /ko -->
这很有效。在这种情况下。
但有时只是“With”就像Simon_Weaver说的那样!
答案 3 :(得分:1)
我更喜欢这种方法
创建自定义绑定
ko.bindingHandlers.safeText = {
update: function (element, valueAccessor, allBindingsAccessor) {
try {
var tryGetValue = valueAccessor()();
ko.bindingHandlers.text.update(element, valueAccessor());
} catch (e) {
ko.bindingHandlers.text.update(element, function () { return ""; });
}
}
};
用法
data-bind="safeText: function() { return my().nested.object.property; }
您需要添加的唯一额外内容是使用'function(){return ...}'包装原始值
然而,这将停止值调用下的所有错误。您可以通过仅查找“未定义”异常来改进自定义绑定。您可能还希望通过添加默认文本选项来改进此绑定。
答案 4 :(得分:1)
对于我来说,大多数这些解决方案在某些情况下都不起作用,我设置了一个属性:
<div role="combobox" data-bind="attr: {
'aria-activedescendant': activedescendant() ? activedescendant().id : null
}">
...
</div>
template
和with
绑定在这里不起作用,因为如果我没有活跃的后代,那么我的div将是空的。对于我的解决方案,我创建了一个可观察的方法:
ko.observable.fn.get = function (propertyName, defaultValue) {
var
self = this(),
propertyValue;
if (self != null) {
propertyValue = ko.unwrap(self[propertyName]);
}
return propertyValue || defaultValue;
}
这允许我将绑定更改为:
<div role="combobox" data-bind="attr: {
'aria-activedescendant': activedescendant.get('id')}">
...
</div>
答案 5 :(得分:1)
上述大部分解决方案对我来说都不是很有用,因为我只想将其应用于foreach
中的单个元素,因此我修改了已接受的答案。接近一点:
<span data-bind="text: ((typeof info).localeCompare('undefined')) ? info : ''"></span>