显示焦点敲除自定义绑定上输入的基本值



我已经在敲除中创建了以下绑定处理程序

所需的功能是,如果字段是数字字段,则在显示时将其格式化为小数点后的"X"位(默认为2),但基本值是所输入的值。

一切都很好,但我想添加一个功能,当输入集中时,它会显示实际值,我只是不知道如何做到这一点。

  1. 用户在输入中输入1.1121
  2. 当他们离开输入时,它的格式为1.11
  3. 如果它们返回到输入(焦点),则显示1.1121进行编辑

我不知道如何实现第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:中为focusblur注册事件处理程序

  • 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 />

最新更新