KnockoutJS拦截到一个小数位

时间:2014-12-09 01:11:46

标签: jquery knockout.js

我知道有人提出了这方面的变化,但我的要求是,不需要格式化/舍入输入的值,我甚至不允许用户在小数点后输入多个数字。我有一些适用于decimalFormatter绑定处理程序的东西,但它很笨重 - 也就是说,它允许你输入一个类似于' 20的值。'并且由于我编写正则表达式的方式,您无法清除所有值。我意识到我可以修改它以接受整个条目的可选数字,但我真正想要的是,如果用户删除该值,它将恢复为0.0。并且,允许他们进入' 20。'然后选项卡(onblur)并将其重新格式化为20.0,使其看起来更完整。目前,如果用户输入' 20。'然后保存表单,它确实存储整数值20,当你重新打开/检索数据库中的值时,它显示20.0,所以它在重新加载时看起来很好。

我考虑过添加一个onblur事件,但是我们不想在覆盖被淘汰的数据绑定时做到这一点。我们希望保留ko视图模型所包含的所有内容,因此这不是一个选项。我也看到一些建议计算的observable(例如这个SO post),但我的绑定已经做到了。第二个想法,淘汰赛event binding是否可以成为这里的方式???

HTML:

<input style="width:38px" data-bind="decimalFormatter: percentage"/>

的javascript:

ko.bindingHandlers.decimalFormatter = {
    init: function (element, valueAccessor) {
    var initialValue;

    //$(element).on('keydown', function (event) {
    $(element).keydown(function (event) {
        initialValue = $(element).val();

        // Allow: backspace, delete, tab, escape, and enter
        if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
        // Allow: Ctrl combinations
        (event.ctrlKey === true) ||
        // Allow decimal/period
        (event.keyCode === 110) || (event.keyCode === 190) ||
        // Allow: home, end, left, right
        (event.keyCode >= 35 && event.keyCode <= 39)) {
            // let it happen, don't do anything
            return;
        }
        else {
            // Ensure that it is a number and stop the keypress
            if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
                event.preventDefault();
            }
        }
    });

    $(element).keyup(function (event) {
        if (!$(element).val().match(/^\d+\.?\d?$/)) {
            event.preventDefault();
            $(element).val(initialValue);
        }
        else
            return;
    });        

    var observable = valueAccessor();

    var interceptor = ko.computed({
        read: function () { return formatWithComma(observable(), 1); },
        write: function (newValue) {
            observable(reverseFormat(newValue, 1));
        }
    });

    if (element.tagName == 'INPUT')
        ko.applyBindingsToNode(element, { value: interceptor });
    else
        ko.applyBindingsToNode(element, { text: interceptor });
    },
    update: function (element, valueAccessor) {
    }
}

// Formatting Functions
function formatWithComma(x, precision, seperator) {
    var options = {
        precision: precision || 2,
        seperator: seperator || '.'
    }
    var formatted = parseFloat(x, 10).toFixed(options.precision);
    var regex = new RegExp('^(\\d+)[^\\d](\\d{' + options.precision + '})$');
    formatted = formatted.replace(regex, '$1' + options.seperator + '$2');
    return formatted;
}

function reverseFormat(x, precision, seperator) {
    var options = {
        precision: precision || 2,
        seperator: seperator || '.'
    }

    var regex = new RegExp('^(\\d+)[^\\d](\\d+)$');
    var formatted = x.replace(regex, '$1.$2');
    return parseFloat(formatted);
}

var viewModel = function () {
    var self = this;
    self.percentage = ko.observable(20.0);
};

var vm = new viewModel();
ko.applyBindings(vm);

JSFiddle

1 个答案:

答案 0 :(得分:4)

我使用AUTONUMERIC插件进行数字格式化,这是可靠而且棒极了。

我只是根据您的要求制作了一个示例,请检查here

查看型号:

var vm = function(){   
this.Amount=ko.observable(""); 
this.OnloadAmount=ko.observable(143); //onLoad Test
ko.bindingHandlers.autoNumeric = {
       init: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var $el = $(el),
              bindings = bindingsAccessor(),
              settings = bindings.settings,
              value = valueAccessor();

            $el.autoNumeric(settings);
            $el.autoNumeric('set', parseFloat(ko.utils.unwrapObservable(value()), 10));
            $el.change(function () {
                value(parseFloat($el.autoNumeric('get'), 10));
            });
        },
        update: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var $el = $(el),
              newValue = ko.utils.unwrapObservable(valueAccessor()),
              elementValue = $el.autoNumeric('get'),
              valueHasChanged = (newValue != elementValue);

            if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0")) {
                valueHasChanged = true;
            }

            if (valueHasChanged) {
                $el.autoNumeric('set', newValue);
            }
        }
    };
}

  ko.applyBindings(new vm());

查看:

<input type="text"  data-bind="autoNumeric:$data.Amount, settings:{mDec:1,aSep: ''} " />

此处mDec:1将数字限制为1的十进制数,asep:''表示不会使用逗号等编号数

PS:我们可以限制输入无效字符并轻松完成许多其他操作。

完整的参考检查here