如何将复选框绑定到值的反转?

时间:2012-01-17 22:28:14

标签: javascript knockout.js

我有一个案例,当我需要将一个复选框和另一个DOM元素的可见性绑定到我的viewModel的布尔属性的反转时:

<input type="checkbox" data-bind="checked: needsReview"> Not Required 
<br>
<div id="Some related text" data-bind="visible: needsReview"> other stuff here </div>
var dataFromSever = { needsReview: true };

var theModel = function (jsonData) {
    var self = this;
    ko.mapping.fromJS(jsonData, {}, self);
}

ko.applyBindings(new theModel(dataFromSever));

我的实际数据模型中有多个这样的属性,所以我不想创建多个ko.computed()字段。我只想绑定"checked: !needsReview()"或同样简单的维护。

3 个答案:

答案 0 :(得分:12)

有一些类似的方法来处理这个。基本思想是你需要创建一个可写的计算observable来绑定复选框。

您可以直接在模型中使用扩展程序或通过向可观察基础(ko.observable.fn)添加函数来执行此操作。

但是,由于您使用的是映射插件,并且可能不希望自定义创建对象的方式或添加其他属性,因此我认为使用自定义绑定是最佳选择。你的模型真的不需要关心维护你的属性的反转,所以我们实际上可以在绑定时做这个部分。

这是一个inverseChecked绑定,它在您的真实可观察对象和绑定之间插入一个可写的计算可观察对象。然后,它只是使用真正检查的绑定来完成它的工作。

ko.bindingHandlers.inverseChecked = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor();
        var interceptor = ko.computed({
                            read: function() {
                                return !value();
                            },
                            write: function(newValue) {
                                value(!newValue);
                            },
                            disposeWhenNodeIsRemoved: element
                        }); 

        var newValueAccessor = function() { return interceptor; };


        //keep a reference, so we can use in update function
        ko.utils.domData.set(element, "newValueAccessor", newValueAccessor);
        //call the real checked binding's init with the interceptor instead of our real observable
        ko.bindingHandlers.checked.init(element, newValueAccessor, allBindingsAccessor);
    },
    update: function(element, valueAccessor) {
        //call the real checked binding's update with our interceptor instead of our real observable
        ko.bindingHandlers.checked.update(element, ko.utils.domData.get(element, "newValueAccessor"));  
    }
};

以下是一个示例:http://jsfiddle.net/rniemeyer/Kz4Tf/

对于visible绑定,您可以执行visible: !needsReview()

答案 1 :(得分:2)

我通常在KO中创建一个与visible相反的自定义bindingHandler:

ko.bindingHandlers['invisible'] = {

    update: function(element, valueAccessor){
        var val = ko.utils.unwrapObservable(valueAccessor());

        ko.bindingHandlers['visible'].update(element, function() { return !val; });            
    }
}

这样,您就可以干净利落地处理您所描述的需求,而不会使您的data-bind陈述变得丑陋!val()

答案 2 :(得分:0)

我更喜欢反转可观察/计算值(不依赖于任何特定绑定)的更通用和通用的方法:

/**
 * A small handy observable / computed function that wraps around the inverse of it's boolean value.
 * @author Nir Azuelos
 * @returns {Function}
 */
ko.observable.fn.inverse = ko.computed.fn.inverse = function() {
    return ko.pureComputed(function() { return !this(); }, this);
};

用法:

<div data-bind="visible: myObservable.inverse()">