Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockout js and globalization

I can't figure out how to handle calculations using knockout js and a non us locale. My comma is , and is validated correctly using the jquery.globalization plugin but the knockout calculation is giving me a NaN. Does knockout js support this in any way or does it exist any workarounds?

Example:

Make the cartEditor example on the knockout js site work allowing decimal values in the quantity field and allowing globalized input (, as comma sign) and output formatting

http://knockoutjs.com/examples/cartEditor.html

I need this to work on a asp.net mvc 3 site because I am running the site using the nb-NO culture and the model binder is expecting , as the comma sign

like image 998
terjetyl Avatar asked Sep 14 '11 22:09

terjetyl


People also ask

What is KnockoutJS used for?

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.

Is KnockoutJS still used?

Today, Knockout. js mostly exists in legacy applications and developers try to move to something newer, like Vue. js.

Is KnockoutJS a framework or library?

Knockout. js is an open source library (under the MIT License) that is pure JavaScript that works with any existing web framework and every mainstream browser. Further, Knockout. js is fully documented with a complete set of online tutorials.

What is Model KnockoutJS?

KnockoutJS library provides an easy and clean way to handle complex data-driven interfaces. One can create self-updating UIs for Javascript objects. It is pure JavaScript Library and works with any web framework. It's not a replacement of JQuery but can work as a supplement providing smart features.


2 Answers

I did something like this by writing a custom binding that wrapped autoNumeric.js for the formatting. (gist)

ko.bindingHandlers.autoNumeric = function ($) {

    function getElementValue(el) {
        return parseFloat(el.autoNumericGet(), 10);
    }

    function getModelValue(accessor) {
        return parseFloat(ko.utils.unwrapObservable(accessor()), 10);
    }

    return {
        init: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var $el = $(el),
                bindings = bindingsAccessor(),
                settings = bindings.settings,
                value = valueAccessor();

            function updateModelValue() {
                value(getElementValue($el));
            };

            $el.autoNumeric(settings);
            $el.autoNumericSet(getModelValue(value), settings);
            $el.change(updateModelValue);
        },
        update: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var $el = $(el),
                newValue = getModelValue(valueAccessor()),
                elementValue = getElementValue($el),
                valueHasChanged = (newValue != elementValue);

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

            if (valueHasChanged) {
                $el.autoNumericSet(newValue);
                setTimeout(function () { $el.change() }, 0);
            }
        }
    };
}

the data binding using this custom autoNumeric binding looks like this:

<input data-bind="autoNumeric:amount, settings:{aSign:'$'}" />

Check out autoNumeric.js extensive options for formatting to see what you can do ewith the settings.

like image 113
craigb Avatar answered Oct 08 '22 04:10

craigb


Modified it to make it compatible with the latest autoNumeric version (1.9.x)

(function($) {

    function getElementValue(el) {
        return parseFloat(el.autoNumeric('get'), 10);
    }

    function getModelValue(accessor) {
        return parseFloat(ko.utils.unwrapObservable(accessor()), 10);
    }

    ko.bindingHandlers.autoNumeric = {
        init: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var $el = $(el),
                bindings = bindingsAccessor(),
                settings = bindings.settings,
                value = valueAccessor();

            function updateModelValue() {
                value(getElementValue($el));
            };

            if (settings.pSign === 's') {
                settings.aSign = ' ' + settings.aSign;
            } else {
                settings.aSign = settings.aSign + ' ';
            }

            $el.autoNumeric(settings);
            $el.autoNumeric('set', getModelValue(value));
            $el.change(updateModelValue);
        },
        update: function (el, valueAccessor, bindingsAccessor, viewModel) {
            var $el = $(el),
                newValue = getModelValue(valueAccessor()),
                elementValue = getElementValue($el),
                valueHasChanged = (newValue != elementValue);

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

            if (valueHasChanged) {
                $el.autoNumeric('set', newValue);
                setTimeout(function () { $el.change() }, 0);
            }
        }
    };
})(jQuery);
like image 42
amitm Avatar answered Oct 08 '22 03:10

amitm