繁体   English   中英

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

[英]show underlying value of input on focus knockout custom binding

我在淘汰赛中创建了以下绑定处理程序(请原谅,现在只是将它们一起砍掉!)

所需的功能是,如果一个字段为数字,则在显示时将其格式设置为小数点后缀“ 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 /> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM