Question

I have observables in my KnockoutJS app and their values are being fetched from an array that's contained globally in the app, eg:

self.observable = ko.observable(App[0].Observable_Value);

For ease, let's say Observable_Value = 10.

This is working as you'd expect it to and the <input> that self.observable is binded to has the correct value in it by default; 10.

What I want to do now is to append the observable with a % in the <input> so the displayed output in the input field will be 10%.

I simply want to append the input value with a % because I need the observable to be readable as a number and not a string to prevent NaN errors later on in the app. The app relies heavily on numbers.

I've tried doing this as a computed function with read/write & parseFloat but to no success.

Any ideas?

Was it helpful?

Solution

I think that the best option in this case would be a custom binding handler.

I simply want to append the input value with a % because I need the observable to be readable as a number and not a string

That is precisely what a binding handler could do - preserve the original value of the observable, but change the way that it is displayed.

I've tried doing this as a computed function

Although a computed function could do the trick, it's usually unecessary unless you want to actually work with the return value from the computed. In this case, since you just want to change the visual display, you don't need a another variable representing the same value.

Here is a very basic one that just puts a % sign in front of the observable's value. See fiddle

ko.bindingHandlers.percent = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var value = ko.unwrap(valueAccessor());
        $(element).text('%' + value);
    }
};

OTHER TIPS

You can add a read/write computable that will add the percent for display, then remove it when setting the underlying value (fiddle):

ko.observable.fn.formatAsPercent = function() {
    var base = this;
    return ko.computed({
        read: function() {
            return base() + "%";
        },
        write: function(newValue) {
            base(parseInt(newValue.replace('%', '')));
        }
    });
};

function ViewModel() {
    var self = this;
    self.number = ko.observable(10); // actual number
    self.percent= self.number.formatAsPercent(); // used for binding to show %
}

var my = { vm : new ViewModel() };

ko.applyBindings(my.vm);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top