Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Binding 源为空/未定义时的KnockoutJS绑定_Binding_Knockout.js - Fatal编程技术网

Binding 源为空/未定义时的KnockoutJS绑定

Binding 源为空/未定义时的KnockoutJS绑定,binding,knockout.js,Binding,Knockout.js,是否有一种更短/更干净的方法来进行空/未定义的测试 <select data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [], optionsText: 'Title', value: SelectedCluster,

是否有一种更短/更干净的方法来进行空/未定义的测试

<select data-bind="options: SelectedBusinessLine() ? SelectedBusinessLine().Clusters() : [],
                               optionsText: 'Title',
                               value: SelectedCluster,
                               optionsCaption: 'Select Cluster..'">
            </select>
我想要

data-bind="options: SelectedBusinessLine().Clusters(),
给予或接受()

或者至少是一个简单的空运算符检查“??”SelectedBusinessLine??[]

或一个绑定参数,用于自动检查null或silent fail

如果可能的话,有什么想法吗?

提供了几种解决方案。相关部分如下:

针对空对象进行保护

如果您有一个包含对象的可观察对象,并且您希望绑定到该对象的属性,那么如果它可能为null或未定义,则需要小心。您可以这样编写绑定:

<span data-bind="text: selectedItem() ? selectedItem().name() : 'unknown'"></span>
<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; });
  }
};
然而,这又给我们的视图模型增加了一些我们可能不想要的膨胀,我们可能不得不对许多属性重复这一点

您可以使用自定义绑定,如:

<span data-bind="text: selectedItem() ? selectedItem().name() : 'unknown'"></span>
<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; });
  }
};
因此,这只是一个可观测对象,它还公开了一个名为safe的计算可观测对象,它将始终返回一个空对象,但实际可观测对象可以继续存储null

现在,您可以像这样绑定到它:

<div data-bind="text: selectedItem.safe().name"></div>

当未知值为null时,您不会看到它,但当
selectedItem
为null时,它至少不会导致错误

我确实认为首选的方法是在这种情况下使用模板绑定,特别是当您有许多这样的属性要绑定时。

我更喜欢这种方法

创建自定义绑定

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 ""; });
        }
    }
};
用法

您需要添加的唯一额外内容是使用“function(){return…}”包装原始值


但是,这将停止值调用下的所有错误。您可以通过只查找“未定义”的异常来改进自定义绑定。您可能还希望通过添加默认文本选项来改进此绑定。

另一个答案引用中未提及的一种方法是将

<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将消失。

使用“With”可以工作(其他可能也可以工作…)

但使用“with”时,角色UI消失/出现,即使内部存在条件。。。例如我需要设置一个状态(真/假)按钮,但只有当状态不为空时

<!-- 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说的那样

在我设置属性的特定情况下,这些解决方案中的大多数都不起作用:

<div role="combobox" data-bind="attr: {
  'aria-activedescendant': activedescendant() ? activedescendant().id : null
}">
  ...
</div>
这允许我将绑定更改为:

<div role="combobox" data-bind="attr: {
  'aria-activedescendant': activedescendant.get('id')}">
  ...
</div>

...

以上大多数解决方案对我来说都不是现成的,因为我只想将其应用于
foreach
中的单个元素,所以我稍微修改了接受答案的方法:

<span data-bind="text: ((typeof info).localeCompare('undefined')) ? info : ''"></span>


模板的唯一问题是,有时我希望将选择框显示为空选项,而不是将其隐藏。我认为框架应该为我们提供一种方法,使我们不必在源代码中使用if null else代码。例如,这里的模板制作示例实际上不起作用-如果模板的“数据”部分为null,那么我就得到了绑定错误。我可以通过为模板绑定应用“if”属性来解决这个问题:@DrewMiller,我认为是jquery模板引擎负责处理空对象。当使用本机敲除模板引擎时,if属性起到了作用。仅供ko.computed参考。请参阅下面的“with”作为最简单、最优雅的最佳答案(这是我们想要的)。谢谢这应该是公认的答案。目前公认的答案过于复杂,无法满足如此简单的要求。这是
with
的核心功能之一。如果您需要访问上述“范围”中的内容,请使用
$parent
@Simon_Weaver。我正准备避免使用ifnot:VM is null”绑定复制UI,而且我没有显式定义的VM(因为它有很多属性)但是简单的mapping.fromJS就足够了。我从来都不知道
如果不
:-)如果您的
状态
observable是一个计算的observable,并且您还启用了ko.options.delferupdates=true;`因为您仍然可以得到空错误-
<div role="combobox" data-bind="attr: {
  'aria-activedescendant': activedescendant() ? activedescendant().id : null
}">
  ...
</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>
<span data-bind="text: ((typeof info).localeCompare('undefined')) ? info : ''"></span>