Search code examples
javascriptknockout.jsknockout-mapping-pluginknockout-2.0knockout-validation

Knockout.js Two-way Binding: Number Formatted as String


I have a bunch of amounts in my view model which are observables, and I want them stored as numbers because they are used in several calculations. However, when I bind them to textboxes in my view, I want them shown as a specially formatted string (1234.5678 => "1,234.57"). What is the best way to accomplish two-way binding in this situation, since I can't just use the value binding with my observable?

The user needs to be able to enter "1,234.56" or "1234.56" in the textbox which will store the number value 1234.56 in the observable, and if I change the number value (3450) via javascript, the textbox value needs to be updated to the new value, but formatted as a string ("3,450").

I appreciate the help!


Solution

  • I would implement something like the following:

    JavaScript:

    function ViewModel() {
        var self = this;
        self.dollarAmount = ko.observable();
    
        self.formattedDollarAmount = ko.computed({
            read: function() {
                return applyFormat(self.dollarAmount()); // pseudocode
            },
            write: function(value) {
                var parsedDollarAmount = parseFloat(value);
                if(!isNaN(parsedDollarAmount)) {
                    self.dollarAmount(parsedDollarAmount);
                }
                else {
                    // recommend adding validation of some sort 
                    // so getting here is less likely
                    alert("invalid dollar amount"); 
                }
            },
            owner: self
        });
    }
    

    HTML:

    <input type="text" data-bind="value: formattedDollarAmount" />
    

    See the documentation on computed observables for more info: http://knockoutjs.com/documentation/computedObservables.html