能否将数据绑定的可见性与布尔型ViewModel属性的否定(" ! ")相关联?

167

我想使用ViewModel上的属性来切换要显示哪个图标,而不必创建一个反向的计算属性。这可能吗?

<tbody data-bind="foreach: periods">
  <tr>
    <td>
      <i class="icon-search" data-bind="visible: !charted, click: $parent.pie_it"></i>
      <i class="icon-remove" data-bind="visible: charted, click: $parent.pie_it"></i>
    </td>
  </tr>
</tbody>

我的ViewModel有一个名为periods的属性,它是一个月份数组,就像这样:

var month = function() {
    this.charted = ko.observable(false);
};

3
@Niko:这并不是一个重复的问题。你所提到的那个问题的提问者已经知道可以绑定反向可观察对象,但想知道为什么需要像函数一样调用它。而这个问题的提问者最开始不知道如何做,并且显然没有发现那个问题。我很高兴在这里找到了这个问题——这主要归功于它描述性的标题。 - Oliver
8个回答

287
使用表达式中的observable时,需要像函数一样访问它,例如:

visible: !charted()


(Note: 保留了HTML标签)

34
也许我们应该做一个隐藏的绑定 :) 我们有启用和禁用。 - John Papa
文档是否与此不符,或者我完全误解了这个页面:http://knockoutjs.com/documentation/css-binding.html? - user736893
算了,我猜“isSevere”不是一个可观察的属性,而只是一个普通的属性,因此让我感到困惑。 - user736893
4
当使用!charted时,你会获得![Function]。[Function]为真值,但如果使用这种语法,[Function]将变为假值并且始终为假。http://jsfiddle.net/datashaman/E58u2/3/ - datashaman
1
实际上,他们在v3.5.0中添加了hidden绑定。 - Grin

53

我同意John Papa的评论,认为应该有一个内置的hidden绑定。使用专门的hidden绑定有两个好处:

  1. 语法更简单,例如hidden: charted,而不是visible: !charted()
  2. 使用的资源更少,因为Knockout可以直接观察可观察对象charted,而不是创建一个computed来观察!charted()

不过,创建一个hidden绑定也很简单,就像这样:

ko.bindingHandlers.hidden = {
  update: function(element, valueAccessor) {
    ko.bindingHandlers.visible.update(element, function() {
      return !ko.utils.unwrapObservable(valueAccessor());
    });
  }
};

你可以像使用内置的 visible 绑定一样使用它:

<i class="icon-search" data-bind="hidden: charted, click: $parent.pie_it"></i>
<i class="icon-remove" data-bind="visible: charted, click: $parent.pie_it"></i>

9
如果没有 return,这对我来说行不通:return !ko.utils.unwrapObservable(valueAccessor()); - Mehmet Ataş
感谢@MehmetAtaş-根据您的评论,我已更正“hidden”绑定。(顺便说一下,在我最初发布这篇文章时,我正在使用CoffeeScript。CoffeeScript的语法不会明确表明返回是否是有意的。) - Dave

10

有点令人困惑,因为你必须这样做

visible:!showMe()

所以,我做了

<span data-bind="visible:showMe">Show</span>
<span data-bind="visible:!showMe()">Hide</span>
<label><input type="checkbox" data-bind="checked:showMe"/>toggle</label>​

我的模型是

var myModel={
    showMe:ko.observable(true)
}
ko.applyBindings(myModel);    

在fiddle中查看 http://jsfiddle.net/khanSharp/bgdbm/


4
您可以使用我的switch/case绑定,其中包括case.visiblecasenot.visible
<tbody data-bind="foreach: periods">
    <tr>
        <td data-bind="switch: true">
        <i class="icon-search" data-bind="case.visible: $else, click: $parent.pie_it"></i>
        <i class="icon-remove" data-bind="case.visible: charted, click: $parent.pie_it"></i>
        </td>
    </tr>
</tbody>

您也可以将其设置为:

        <i class="icon-search" data-bind="casenot.visible: charted, click: $parent.pie_it"></i>
        <i class="icon-remove" data-bind="case.visible: $else, click: $parent.pie_it"></i>

我刚意识到这是一个老问题,但希望对某人有用。 - Michael Best

1
为了让绑定知道属性的变化,我复制了可见绑定处理程序并将其反转:
ko.bindingHandlers.hidden = {
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        var isCurrentlyHidden = !(element.style.display == "");
        if (value && !isCurrentlyHidden)
            element.style.display = "none";
        else if ((!value) && isCurrentlyHidden)
            element.style.display = "";
    }
};

0

免责声明:此解决方案仅供娱乐目的。

ko.extenders.not = function (target) {
    target.not = ko.computed(function () {
        return !target();
    });
};

self.foo = ko.observable(true).extend({ not: null });

<div data-bind="text: foo"></div>     <!-- true -->
<div data-bind="text: foo.not"></div> <!-- false -->

<!-- unfortunately I can't think of a way to be able to use:
    text: foo...not
-->

0

我遇到了同样的问题,即如何使用布尔可观察对象的相反值。我找到了一个简单的解决方案:

var ViewModel = function () {
var self = this;

// When program start, this is set to FALSE
self.isSearchContentValid = ko.observable(false);


self.gatherPlacesData = function () {

   // When user click a button, the value become TRUE
   self.isSearchContentValid(true);

};

现在,在你的HTML文件中,应该这样做
<p data-bind = "visible:isSearchContentValid() === false"> Text 1</p>
<p data-bind = "visible:isSearchContentValid"> Text 2</p>

当程序开始时,只有“Text1”可见,因为“false === false is TRUE”,Text2不可见。
假设我们有一个按钮,它在点击事件上调用gatherPlacesData。现在,由于“true === false is FALSE”,Text1将不可见,而只有Text2可见。
另一个可能的解决方案是使用计算可观察对象,但我认为这对于如此简单的问题来说是一个过于复杂的解决方案。

-1

也可以像这样使用隐藏

 <div data-bind="hidden: isString">
                            <input type="text" class="form-control" data-bind="value: settingValue" />
                        </div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接