Knockout自定义绑定到对象

时间:2013-11-04 01:09:44

标签: javascript binding knockout.js

我目前正在设计一个浏览器内计算器,我想要的功能是创建一个输入框,并将其绑定到视图模型中的对象。

此对象将具有一个名为value的属性,该属性将是输入框显示的属性,但我还希望它具有最小和最大限制,如果超出这些限制,则会将框的背景颜色更改为红色。

我得到了基本的输入绑定,但我在为输入绑定创建自己的自定义绑定包装时也遇到了麻烦。

我的HTML:

<td><input data-bind="calcVar: resistance" type="text" size="16" /></td>

我的Javascript:

&#34; class&#34;保存所有数据

var calcVar = function(value, lowerBound, upperBound) {
        this.value = ko.observable(value);
        this.lowerBound = ko.observable(lowerBound);
        this.upperBound = ko.observable(upperBound);
};

在视图模型中创建变量:

this.fSwAct = ko.observable(new calcVar(200, 100, 100, 0, 1000));

启动功能

// Start-up function
j(document).ready(
    function StartUp()
    {           
        // Create custom binding
        ko.bindingHandlers.calcVar = {
             init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                  ko.bindingHandlers.value.init(element, valueAccessor()().value, allBindings, viewModel, bindingContext);
             },
             update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                  // Call value binding (child binding)
                  ko.bindingHandlers.value.update(element, valueAccessor()().value, allBindings, viewModel, bindingContext);
             }
        };
        // Activates knockout.js
        var app = new AppViewModel();
        ko.applyBindings(app);  
    }
);

虽然正在调用自定义绑定功能,但输入绑定似乎不起作用,并且其他计算字段在更改值时不会更新。我觉得这与我创建calcVar&#34; class&#34;的方式有关。或者将其传递给输入绑定。

1 个答案:

答案 0 :(得分:2)

你实际上并不需要自定义绑定来使背景变红,你可以只使用样式内置绑定。但是,进行自定义绑定会产生更清晰的标记。这里有两个示例实现,一个是自定义绑定,一个没有(小提琴:http://jsfiddle.net/EWdmV/5/):

HTML:

<span>--------- no custom binding ---------</span><br />
<td><input data-bind="value:value, valueUpdate:'afterkeydown', style:{ 'background-color' : isOutsideBounds() ? 'red':'white'}" type="text" size="16" /></td>


<span>--------- with custom binding ---------</span><br />
<td><input data-bind="value:value, valueUpdate:'afterkeydown', calcVar: isOutsideBounds" type="text" size="16" /></td>

JS:

var CalcVar = function(value, lowerBound, upperBound) {
        var self = this;
        self.value = ko.observable(value);
        self.lowerBound = ko.observable(lowerBound);
        self.upperBound = ko.observable(upperBound);
        self.isOutsideBounds = ko.computed(function(){
            var val = parseFloat(self.value(),10);
            console.log(val);
            console.log(val > self.upperBound() || val < self.lowerBound());
        return val > self.upperBound() || val < self.lowerBound();
    }, self);

};

ko.bindingHandlers.calcVar = {
    init:function(element, valueAccessor){        
    },
    update:function(element, valueAccessor){        
        if(valueAccessor()()){
            $(element).css("backgroundColor", "red");
        } else {
            $(element).css("backgroundColor", "white");
        }
    }
}

ko.applyBindings(new CalcVar(100, 10,1000));

编辑:如果你真的想要更短的标记,下面是另外两个选择,使用模板,并使用调用renderTemplate的自定义绑定(可能这是你需要的)(更新的小提琴:http://jsfiddle.net/EWdmV/14/):< / p>

HTML:

<span>--------- with custom binding tempalate ---------</span><br />
<div data-bind="template:{name:'superCalcTemplate', data:resistor1}" ></div>
<br />
<span>--------- with super custom binding ---------</span><br />
<div data-bind="superCalcVar:resistor1"></div>
<div data-bind="superCalcVar:resistor2"></div>

<script type="text/html" id="superCalcTemplate">
    <input data-bind="value:value, valueUpdate:'afterkeydown', calcVar: isOutsideBounds" type="text" size="16" />    
</script>

JS:

ko.bindingHandlers.calcVar = {
    init:function(element, valueAccessor, allBindings, viewModel, bindingContext){        
    },
    update:function(element, valueAccessor, allBindings, viewModel, bindingContext){        
        if(valueAccessor()()){
            $(element).css("backgroundColor", "red");
        } else {
            $(element).css("backgroundColor", "white");
        }
    }
}

ko.bindingHandlers.superCalcVar = {
    init:function(element, valueAccessor, allBindings, viewModel, bindingContext){   

        ko.renderTemplate("superCalcTemplate", valueAccessor(), {}, element, "replaceChildren");
         return { controlsDescendantBindings: true };              

    },
    update:function(element, valueAccessor, allBindings, viewModel, bindingContext){                               
    }
}