Is it possible to use KnockoutJS with a masked inp

2019-02-02 02:30发布

I´m using that plugin : https://github.com/plentz/jquery-maskmoney to format my money editor...

I tried to use KnockoutJS in that editor, but it does not work... Without that mask all works fine...

My code test is simple :

<input id="Price" data-bind="value: Price"  type="text"  name="Price"> 

Javascript to Mask input

$("#Price").maskMoney({ symbol: 'R$ ', showSymbol: true, thousands: '.', decimal: ',', symbolStay: false });

And KnockoutJS

var ViewModel = function () {
            this.Price = ko.observable();

            this.PriceFinal= ko.computed(function () {
                return this.Price() 
            }, this);
        };

        ko.applyBindings(new ViewModel()); 

3条回答
啃猪蹄的小仙女
2楼-- · 2019-02-02 03:07

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());
查看更多
一夜七次
3楼-- · 2019-02-02 03:10

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.

查看更多
再贱就再见
4楼-- · 2019-02-02 03:31

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 }" />
查看更多
登录 后发表回答