当源为空/未定义时,KnockoutJS绑定
有没有更简洁的方法来做null / undefinedtesting?
<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(),
给或拿(()
或者至less一个简单的空操作符检查'??' SelectedBusinessLine? []
或者一个绑定参数来自动检查是否为空或者无提示失败。
任何想法,如果这是可能的?
本页提供了几个解决scheme。 相关部分是这样的:
防止空对象
如果你有一个包含一个对象的观察值,并且你想要绑定到该对象的属性,那么你需要小心,如果有可能是空的或未定义的。 你可以写你的绑定,如:
<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
。 这是最简单的解决scheme。
只是为了探索一些select,这里有几个select:
您可以使用计算的可观察值,就像我们之前做的一样。
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,但它仍然相当冗长。
另外一个select是创build一个扩展的observable,它提供了一个访问属性的安全方法,同时仍然允许实际的值为null。 可能看起来像:
ko.safeObservable = function(initialValue) { var result = ko.observable(initialValue); result.safe = ko.dependentObservable(function() { return result() || {}; }); return result; };
所以,这只是一个可观察的事件,它也暴露了一个名为safe的计算的observable,它总是返回一个空的对象,但实际的observable可以继续存储null。
现在,你可以像这样绑定它:
<div data-bind="text: selectedItem.safe().name"></div>
当它为空时,你不会看到未知的值,但是当selectedItem
为空时,它至less不会导致错误。
我认为在这种情况下,首选选项是使用模板绑定,特别是如果你有许多这些属性绑定。
一种方式在其他方面引用的优秀页面中没有提到的一个方法是使用
<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
为null,则整个UI将消失。
“With”作品(可能其他作品也是…)
但是随着“与”的angular色用户界面消失/出现,即使有内部条件…例如…我需要设置一个状态(真/假)button,但只有当状态不为空.. 。
<!-- 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 -->
这工作。 在这种情况下。
但是有时候,像Simon_Weaver这样的“With”作品就是这么说的!
我更喜欢这种方法
创build一个自定义绑定
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 …}'来包装你的原始值
但是,这将会阻止值调用下的所有错误。 您可以通过仅查找“未定义”例外来改进自定义绑定。 您也可以通过添加默认文本选项来改善此绑定。
这些解决scheme中的大多数在某些情况下不适用于我,我设置了一个属性:
<div role="combobox" data-bind="attr: { 'aria-activedescendant': activedescendant() ? activedescendant().id : null }"> ... </div>
template
和绑定在这里不起作用,因为如果我没有一个活跃的后代,那么我的div将是空的。 对于我的解决scheme,我创build了一个可观察的方法:
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>
上面的大多数解决scheme对我来说并不适用,因为我只是想将它应用到一个foreach
的单个元素,所以我稍微修改了接受的答案的方法:
<span data-bind="text: ((typeof info).localeCompare('undefined')) ? info : ''"></span>