使用Knockout绑定一个可观察的元素?

时间:2012-02-27 12:42:53

标签: javascript mvvm knockout.js

这不是一个理想的情况,但是由于我正在使用的另一个敲除绑定我处于这样一种情况:我需要获得一个可观察的元素,如果它确实绑定到任何东西。

有没有办法做到这一点?

==更新==

我不想添加任何额外的上下文,因为它会混淆问题,但因为它可能会得到一个更符合预期的答案就是这个场景。

我正在使用敲除验证绑定,它使用ko.validation.group(model)方法公开所有错误。但问题是只有给你文本错误,它没有给你任何关于模型的哪个部分给你那些错误的背景。所以我对源进行了一些小改动,现在传回与每个错误绑定的observable,因为这对于一些场景可能很有用,但是从这里我需要能够将它绑定到一个元素,这样我才能显示一些某种形式的在线验证。

Knockout Validation提供了一个非常基本的内联验证,它可以在元素之后创建一个span,你可以给它一个类,但这对我的需求来说太基础了,因为目前我们正在使用Qtip和其他通知系统来显示验证错误,因此我需要能够有一个Dom元素和一个错误。到目前为止,我有一个observable和一个错误,但我需要将该可观察对象(可能是模型中的任何ko.observable()属性)与其给定的DOM元素绑定,如果它确实有元素绑定。

由于我所拥有的只是一个对象而且我使用的是从模型驱动的验证而不是UI,因此问题实际上并不是通过自定义绑定来解决的。理想情况下,我需要能够破解将可观察对象(未知ko.observable())与元素结合起来。

不要过于具体项目,但我当前的项目抽象了事件被触发的验证(即EventSystem.SendEvent(ValidationEvents.ValidationFailed, <element>, <error>))然后验证系统侦听这些事件并将错误绑定到元素,无论是工具提示,一个咆哮的样式通知,一个警告框等。所以我试图找到从模型observables而不是ui的DOM元素(即jquery-ui)驱动验证时保持这种抽象的最佳方法

==编辑2 ==

我被Knockout Validation知道可观察元素放入自己的验证元素的方式有点抛出,但是他们只是背负现有的值绑定,所以我只是想改变它来添加元素任何基于isValidatable()方法的验证元素,至少每个错误的方式我可以将它绑定到一个observable,对于任何带有元素绑定的observable,我可以将它们绑定到元素,如果没有,那么它很好,他们只是形成广泛的验证错误。我会试一试,因为这应该是(尚未测试):

if(utils.isValidatable(valueAccessor())) {
    valueAccessor().extend({hasElementalBinding: true, elementalBinding: element});
}
else { 
    valueAccessor().extend({hasElementalBinding: false});
}

registerValueBindingHandler的第250行附近,我会暂时搁置这个问题,因为其他人有更好的解决方案。

2 个答案:

答案 0 :(得分:18)

我做了类似于你上面提到的事情。我的数据绑定标记包含自定义绑定:

data-bind="... myvalidationbinding: myobservable"

然后在我的绑定处理程序中,我扩展了observable

ko.bindingHandlers.myvalidationbinding = {
  init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
    valueAccessor().extend({element: element });
  }
};

最后我的扩展名是

ko.extenders.element = function (target, element) {
  target.DOMElement = element;
}

现在我可以订阅由knockout.validation给出的isValid(),如果无效,去获取observable绑定的元素,然后用jQuery操作它。

答案 1 :(得分:5)

这不会很快,所以我肯定会缓存结果,但使用jQuery的属性选择器:

$('[data-bind*="Property"]')

*=属性包含选择器:http://api.jquery.com/attribute-contains-selector/

显然,这不会捕获使用.subscribe方法手动订阅的任何内容,但我不确定如何从函数中提取元素。

免责声明:虽然这个解决方案可能会有效,但这听起来像是一个可怕的想法,我会改为编写自定义绑定(如评论中所述)或找到其他解决方案。