Is it possible to use KnockoutJS with a masked input?

送分小仙女□ 提交于 2019-11-30 02:22:44

You should use a writable computed observable.

function MyViewModel() {
    this.price = ko.observable(25.99);

    this.formattedPrice = ko.computed({
        read: function () {
            return '$' + this.price().toFixed(2);
        },
        write: function (value) {
            // Strip out unwanted characters, parse as float, then write the raw data back to the underlying "price" observable
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            this.price(isNaN(value) ? 0 : value); // Write to underlying storage
        },
        owner: this
    });
}

ko.applyBindings(new MyViewModel());

You can also register a binding handler for MaskMoney with Knockout, something like:

$(document).ready(function () {

ko.bindingHandlers.currencyMask = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().currencyMaskOptions || {};
        $(element).maskMoney(options);

        ko.utils.registerEventHandler(element, 'focusout', function () {
            var observable = valueAccessor();

            var numericVal = parseFloat($(element).val().replace(/[^\.\d]/g, ''));
            numericVal = isNaN(numericVal) ? 0 : numericVal;

            observable(numericVal);
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).unmaskMoney();
        });
    },

    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());

        $(element).val(value);
        $(element).trigger('focus');
    }
};

});

and then as your binding:

<input type="text" data-bind="currencyMask: MyModel.TotalCost, currencyMaskOptions: { symbol: '$', showSymbol: true, thousands: ',', precision: 0 }" />

Note that I tweaked the MaskMoney plugin slightly to use input.on('focusout.maskMoney', blurEvent); rather than input.bind('blur.maskMoney',blurEvent); because it was not triggering an update on losing focus via mouse clicking, only on tabbing.

I'm new to Knockout and have been finding the binding handler approach really nice for plugins like this and datepickers, etc.

If you are using jquery.formatcurrency you could do:

ko.bindingHandlers.currencyMask = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().currencyMaskOptions || {};
        $(element).formatCurrency(options);
        $(element).keyup(function () {
            $(element).formatCurrency(options);
        });


        ko.utils.registerEventHandler(element, 'focusout', function () {
            var observable = valueAccessor();
            observable($(element).val());
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).formatCurrency('destroy');
        });
    },

    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());

        $(element).val(value);
        $(element).trigger('focus');
    }
};

<input data-bind="currencyMask: priceVal, currencyMaskOptions: { roundToDecimalPlace: 0 }" />
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!