扩展ko.observable或访问绑定到observable的DOM节点

时间:2016-12-24 13:55:19

标签: typescript knockout.js

我正在使用TypeScript和Knockout编写应用程序,并且在最近几天尝试扩展viewmodel中使用的ko.observable对象,以便能够执行以下操作:

HTML:

<input type="text" data-bind="value: myvalue" />
<button data-bind="click: enable">Enable</button>
<button data-bind="click: disable">Disable</button>

视图模型:

interface KnockoutObservableFunctions<T> {
    enabled(enabled: boolean): void;
}

class MyModel {

    public theValue: KnockoutObservable<string>;

    constructor() {
        ko.observable.fn.enabled = function (enabled: boolean)  {
            // This is not working because I don't have access to the
            // elements, but it should illustrate my intentions.
            $(elements[0]).prop("disabled", !enabled);
        }

        this.theValue = ko.observable("A string");
    }

    public enable(): void {
        this.theValue.enabled(true);
    }
    public disable(): void {
        this.theValue.enabled(false);
    }
}

也就是说,我想访问绑定到我在fn上附加的自定义函数中的observable的DOM节点,如上面的代码所示。我怎么做?我尝试过自定义绑定,但这似乎不太合适。

我知道Knockout中的启用/禁用绑定,我最终想做的事情可以通过使用其他observable来完成,即将viewValueEnabled observable添加到viewmodel。

1 个答案:

答案 0 :(得分:0)

就个人而言,我会选择添加enabled观察者的扩展器。我还要注意每当你想要一个带有DOM元素的东西时,自定义绑定是唯一的方法 。 :)

然后,您有两个选择:

  • enable绑定添加到嵌套的observable:enable:myValue.enabled`(你说你不想使用这个绑定,但我想你应该和我提到它给它一个完整的答案)
  • 创建一个结合了valueenable绑定的绑定。

在下面的示例中,您可以看到两个绑定。我没有真正看到第二种方法的好处,因为它模糊了逻辑,最终可能出现在许多不同的绑定中。 (例如,你需要另一个textInput绑定。)

(我不知道打字稿,所以这个例子是普通的js。希望没关系。)

ko.extenders.enabled = function(target, initialVal) {
  target.enabled = ko.observable(initialVal);
  return target;
}

ko.bindingHandlers.enabledValue = {
  init: function(el, va) {
     ko.applyBindingsToNode(el, { 
       value: va(),
       enable: va().enabled
     });
  }
}

var VM = function() {
  this.myValue = ko.observable("test")
    .extend({
      enabled: true
    });

  this.enable = this.myValue.enabled.bind(null, true);
  this.disable = this.myValue.enabled.bind(null, false);


}

ko.applyBindings(new VM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div>
  Two bindings:
  <input type="text" data-bind="value: myValue, 
                                enable: myValue.enabled" />
</div>

<div>
  One binding:
  <input type="text" data-bind="enabledValue: myValue" />
</div>
<button data-bind="click: enable">Enable</button>
<button data-bind="click: disable">Disable</button>