[英]show underlying value of input on focus knockout custom binding
我在淘汰赛中创建了以下绑定处理程序(请原谅,现在只是将它们一起砍掉!)
所需的功能是,如果一个字段为数字,则在显示时将其格式设置为小数点后缀“ X”(默认为2),但输入的基础值将为小数。
一切正常,但是我想添加一个功能,当输入成为焦点时,它会显示实际值,我只是不知道该怎么做。
即
是第3点,我不知道该如何实现,因为它现在显示1.11,然后在模糊时覆盖?
谁能为我指出正确的方向-基本上我可以在哪里访问基础值并将焦点替换为基础值?
为简便起见,我删除了一些其他的“装饰”代码,这些代码包装了输入,因为它们并不相关。
提前致谢。
ko.bindingHandlers.specialInput = {
init: function (element, valueAccessor, allBindingsAccessor) {
var value = valueAccessor();
var decimals = allBindingsAccessor().decimals || 2;
var formatString = "";
var interceptor = ko.computed({
read: function () {
if(isNumeric(ko.unwrap(value))){
//to do if time - replace this with a function that will accept any number of decimals
if(decimals == 0){
formatString = "0,0";
}
if(decimals == 1){
formatString = "0,0.0";
}
if(decimals == 2){
formatString = "0,0.00";
}
if(decimals == 3){
formatString = "0,0.000";
}
if(decimals == 4){
formatString = "0,0.0000";
}
if(decimals == 5){
formatString = "0,0.00000";
}
return numeral(ko.unwrap(value)).format(formatString);
}else{
return ko.unwrap(value);
}
},
write: function (newValue) {
if ($.trim(newValue) == '')
value("");
else
if(isNumeric(newValue)){
value(numeral().unformat(newValue));
value.valueHasMutated();
}else{
value(newValue);
value.valueHasMutated();
}
}
}).extend({notify: 'always'});
if (element.tagName.toLowerCase() == 'input') {
ko.applyBindingsToNode(element, {
value: interceptor
});
} else {
ko.applyBindingsToNode(element, {
text: interceptor
});
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = ko.unwrap(valueAccessor());
return ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
}
};
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
我不会用计算出的interceptor
来实现这一点。
我宁愿执行以下操作:
在init
注册事件处理程序中,用于在init
进行focus
和blur
处理:
focus
处理程序上,您必须在输入中显示基础值 blur
处理程序上,您必须将数字存储在文本框中,并在输入中显示四舍五入的值 在update
您必须存储实际值,并将其显示在文本框中。 更新值时,文本框很可能没有焦点,因此应该放心显示四舍五入的值。 但是,如果您认为在某些情况下可以将其聚焦,则可以执行以下操作来测试它以确定如何显示该值: 使用jQuery测试输入是否具有焦点
ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var $element = $(element);
$element.on('focus', function() {
// Show raw value:
$element.val(/* raw value */);
});
$element.on('blur', function() {
// Update the observable with the value in the input
ko.unwrap(valueAccessor())( /* get raw value from input */);
// Show the rounded value
$element.val(/* rounded value */);
});
// Update will be called after init when the binding is first applied,
// so you don't have to worry about what it's initially shown
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// When the value changes, show it in the input
$.element.val(/* if focused show raw, if not, show roundede*/);
}
};
如果您确定只将其与input
和可写可观察对象一起使用,则此代码是安全的。 如果对此有疑问,则应添加许多检查,例如检查使用jQuery .val()
或.text()
的元素的种类,检查绑定表达式是否可写,以观察其值,等等。
注意:有很多事情需要监督:销毁元素时我们不再需要的对象(例如,如果使用'if','whit'或'template',则可能发生)。 在这种情况下,我认为您不需要这样做,但是请查看以下内容: 自定义处理逻辑(如果您认为需要销毁某些东西)。
在绑定处理程序中使用jQuery并没有错,但是您也可以使用现有的绑定处理程序非常简单地完成此操作。 可以将其整合到组件中以进行重用(尽管在我的示例中我没有这样做)。
您只需要一个值的后备存储,然后计算的结果就会返回后备存储或格式化的后备存储,具体取决于输入是否具有焦点(使用hasFocus
绑定)。
vm = (function() { var editing = ko.observable(false), backingStore = 0, value = ko.computed({ read: function() { return editing() ? backingStore : (+backingStore).toFixed(2); }, write: function(newValue) { backingStore = newValue; } }); return { editing: editing, value: value } }()); ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <input data-bind="hasFocus: editing, value: value" /> <input />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.