Numbers get converted to strings

5,216 views
Skip to first unread message

Roberto Yudice

unread,
Apr 23, 2011, 8:56:08 PM4/23/11
to KnockoutJS
Hello, I return JSON from the server and then convert it to a
viewmodel using ko.fromJSON but the values that are numbers in my json
suddenly become strings in the viewmodel, is there anyway to specify
the data type for an observable? or to prevent my values to being
converted to strings?

rpn

unread,
Apr 23, 2011, 10:03:54 PM4/23/11
to knock...@googlegroups.com
So, it sounds like you are using the mapping plugin (ko.mapping.fromJSON) to turn your JSON from the server into your viewModel, right?  Are you sure that the numbers in your JSON are not wrapped in quotes?  If they are numbers, then it looks like the mapping plugin will keep them as numbers.

Otherwise, is this happening after somebody edits an input field?  If you have a number in your view model, bind it to an input field, then edit that input field, it will become a string.

One way to prevent that is to bind your edit field to a writable dependentObservable that will make sure that it is a number when writing back to the real observable.

So, you could bind to "editValue" here:

viewModel.realValue ko.observable(10);
viewModel.editValue ko.dependentObservable({
    readfunction({
        return this.realValue();
    },
    writefunction(newValue{
        var parsedValue parseFloat(newValue);
        this.realValue(isNaN(parsedValuenewValue parsedValue);
    },
    ownerviewModel
});


or you can create a special observable that forces the value to be numeric like:

ko.numericObservable function(initialValue{
    var _actual ko.observable(initialValue);

    var result ko.dependentObservable({
        readfunction({
            return _actual();
        },
        writefunction(newValue{
            var parsedValue parseFloat(newValue);
            _actual(isNaN(parsedValuenewValue parsedValue);
        }
    });

    return result;
};


Now, you can use this like any observable:

viewModel.realValue ko.numericObservable(10);

I might have slightly misinterpreted your question, if your numeric values are not bound to input fields.  Let me know if you are talking about a different scenario.

Sample with these two options here: http://jsfiddle.net/rniemeyer/RJbdS/




Roberto Yudice

unread,
Apr 23, 2011, 10:55:45 PM4/23/11
to KnockoutJS
Yes, the values with which I'm having the issue are bound to input
fields, however my viewmodel has an object which has about 30 numeric
properties that are bound to a form, is there a way to do this without
having to wrap all my properties in writable observables? the other
option I can think of is to cast to number everytime I do a math
operation.

fla...@gmail.com

unread,
Apr 24, 2011, 4:51:32 AM4/24/11
to KnockoutJS
> is there a way to do this without having to wrap all my properties in writable observables?

Out of interest, could you clarify why you don't want to wrap
properties in writable observables to compose in this behavior? RPN's
technique of defining "ko.numericObservable" will mean your code can
be very succinct and expressive.

If you could indicate what in particular you're unsatisfied with about
this solution, we may be able to come up with an alternative that
better matches your goals.

Thanks
Steve

Roberto Yudice

unread,
Apr 24, 2011, 4:47:29 PM4/24/11
to KnockoutJS
Well I mean, I would have to write a lot of code to wrap all my 30
properties right? Or is there a way to automatically wrap all numbers?

rpn

unread,
Apr 25, 2011, 11:24:29 AM4/25/11
to knock...@googlegroups.com
If you define something like a "ko.numericObservable", then you can just start using that in place of ko.observable where appropriate.

However, this does mean that you can't just use the default behavior of the mapping plugin.  You would have to use the "create" hooks or map it yourself using something like ko.utils.arrayMap.  Otherwise, you would have to go through all of your fields and convert them to numbers prior to sending it back to the server.  So, you would have to do the mapping on the front-end or back-end.

Another thought would be to create a "numericValue" binding that would ensure that when it reads the value from a field, it converts it to a number, if possible.  The code would likely be identical to the current value binding, but with some parsing included instead of ko.selectExtensions.readValue.  I suppose that you could even replace ko.selectExtensions.readValue at run-time with your own implementation that tries to convert numbers.

fla...@gmail.com

unread,
Apr 25, 2011, 2:00:23 PM4/25/11
to KnockoutJS
> Another thought would be to create a "numericValue" binding

That's a brilliant idea. Here's a sample implementation:

ko.bindingHandlers.numericValue = {
init : function(element, valueAccessor, allBindingsAccessor) {
var underlyingObservable = valueAccessor();
var interceptor = ko.dependentObservable({
read: underlyingObservable,
write: function(value) {
if (!isNaN(value)) {
underlyingObservable(parseFloat(value));
}
}
});
ko.bindingHandlers.value.init(element, function() { return
interceptor }, allBindingsAccessor);
},
update : ko.bindingHandlers.value.update
};

Runnable example: http://jsfiddle.net/8DbyV/

Notice how it's possible for bindings to directly reference other
bindings, so as to inherit the behavior of another binding and just
wrap some extra functionality around it. In this example, the
"numericValue" binding wraps an interceptor dependentObservable around
the one being bound.

Regards
Steve

rpn

unread,
Apr 25, 2011, 2:33:43 PM4/25/11
to knock...@googlegroups.com
I like that implementation!  Instead of going out and finding the fields that need to be wrapped, we let them come to us.   That could be interesting in many cases where we don't really want to do complex mappings.

This also reminded me how I am silly to keep writing things like:

read: function() {
  return someObservable();
}

rather than just:

read: someObservable

Roberto Yudice

unread,
Apr 30, 2011, 9:46:22 PM4/30/11
to KnockoutJS
Thanks a lot for your help! I used both of your solutions.

On Apr 25, 12:33 pm, rpn <rnieme...@gmail.com> wrote:
> I like that implementation!  Instead of going out and finding the fields
> that need to be wrapped, we let them come to us.   That could be interesting
> in many cases where we don't really want to do complex mappings.
>
> This also reminded me how I am silly to keep writing things like:
>
> *read: function() {*
> *  return someObservable();*
> *}*
>
> rather than just:
>
> *read: someObservable*

Kenneth

unread,
May 2, 2011, 1:38:33 PM5/2/11
to KnockoutJS
I tried it with templating and I get the following error: uncaught
exception: Pass a function that returns the value of the
dependentObservable.

I created a fiddle here, but I don't think jsFiddle support the
template tag. http://jsfiddle.net/MXXPv/3/

Anyway how to get it working with template?

Ken

rpn

unread,
May 2, 2011, 4:56:16 PM5/2/11
to knock...@googlegroups.com
Hi Ken-
The solution that was described depends on the numeric value being an observable.  So, you can fix your issue by defining your age property as an observable.  Here is a sample: http://jsfiddle.net/rniemeyer/wtZ9X/

Kenneth

unread,
May 3, 2011, 2:05:24 AM5/3/11
to KnockoutJS
Hi

Thanks. But I serialize the serverside model with Newtonsoft JSON, so
the questions is, what is a good way to filter those properties, that
has be observable? With some jQuery map function maybe?

Ken

rpn

unread,
May 3, 2011, 1:19:23 PM5/3/11
to knock...@googlegroups.com
Hi Ken-
Many people use the mapping plugin.   Otherwise, you can manually map it using something like $.map or ko.utils.arrayMap.  This post describes the basic idea.  

Hope this helps.

Kenneth

unread,
May 4, 2011, 3:39:26 PM5/4/11
to KnockoutJS
Thx. It's working now with the mapping plugin.

Alexander Kellett

unread,
Jul 30, 2011, 7:23:57 AM7/30/11
to knock...@googlegroups.com
Thanks for the numericValue handler!

This did the trick for my problem (even using optionsValue with numbers in the used fields I still got strings when a value was picked).

I also added 
                if (value.length == 0) {
                    underlyingObservable(null);
                }


danwe...@gmail.com

unread,
Aug 13, 2011, 2:27:52 PM8/13/11
to knock...@googlegroups.com
I realise the OP has a solution, but for others that may come across this post, I found a simple solution also:

var viewModel {
  thisMustStayANumber: ko.observable(0)
}

viewModel.enforceNumber = ko.dependantObservable(function () {
  if (typeof(this.thisMustStayANumber() !== "number")) {
    this.thisMustStayANumber(parseInt(this.thisMustStayANumber));
  }
}, viewModel);

Whenever the observed thisMustStayANumber property changes, the enforceNumber dependantObservable checks it is still a number, and converts it to a number if it isn't.

Seems robust enough, hope it helps some else :)

gaffe

unread,
Aug 15, 2011, 3:48:57 PM8/15/11
to knock...@googlegroups.com
I am trying to enforce certain rules for users when entering numbers and formatting something like this:

So that if you enter "$1234.40" it instantly becomes 1,234 for example.

Or I think it will be very useful in a textarea if someone pastes quotes in from word I want certain character codes to be replaced with "", etc.

But, does anyone know how I could get this to work on initial population and whenever the value is updated, not just after a user types something?

gaffe

unread,
Aug 15, 2011, 3:50:42 PM8/15/11
to knock...@googlegroups.com
In case that link does not work here it is again, wasn't logged in, oops: http://jsfiddle.net/pilavdzic/8DbyV/3/

gaffe

unread,
Aug 15, 2011, 3:57:09 PM8/15/11
to knock...@googlegroups.com
Good idea, but I think really need a custom binding because my viewmodel is dynamic and comes from the server, so I'm not sure how to easily add that dependentovserable onto each number field.

See my fiddle and question above (I replied/modified someone elses fiddle from earlier in the thread) so my post appears above. Anyone know how that can be accomplished?

Thanks.

rpn

unread,
Aug 15, 2011, 8:36:13 PM8/15/11
to knock...@googlegroups.com
If you really want the conversion to happen when the value is set programmatically or by a user, then I think that it would be best to move the conversion to your model.

Here is a sample of creating a numericObservable that you can use in place of a normal observable.  It contains similar logic to what you had in the binding, but can be used in your view model.  

Enis Pilavdzic

unread,
Aug 16, 2011, 12:18:09 AM8/16/11
to knock...@googlegroups.com
Thanks, this is a great way to accomplish this! 

But can a custom binding be created somehow that will turn a normal observable into this numericobservable?

I want to use a custom binding because that is the most convenient way for me to indicate the type that applies to each field. My model comes from the server, and I want to have DateObservables NumericObservables, TextareaObservables, etc that all filter different things and behave differently. I can make a custom binding for each, but I don't wish to manually do something else on a field by field basis beyond that if possible?

rpn

unread,
Aug 16, 2011, 9:38:05 AM8/16/11
to knock...@googlegroups.com
If you are unable to assign these "types" in your model, then there are ways to do this through a binding.  To keep it simple, I would maybe consider moving back to your last idea that you posted here: http://jsfiddle.net/pilavdzic/8DbyV/3/.  If you add a line like this after you define the "interceptor", then it will send your initial data through the conversion.

interceptor(underlyingObservable().toString());

The only thing that you would be missing it handling programmatic changes to the value, but you would likely be in control of that code.

I personally like it when the view model handles it, as you can just bind normally, but go with whatever works best for you.  Hope this helps.

Nikolai Zujev

unread,
Sep 7, 2011, 12:03:34 PM9/7/11
to knock...@googlegroups.com
hey rpn,

Here is ported numericObservable to KO-1.3 extenders: integer & float


rpn

unread,
Sep 7, 2011, 12:17:12 PM9/7/11
to knock...@googlegroups.com
Very nice!

bruin...@gmail.com

unread,
Oct 7, 2011, 1:58:34 PM10/7/11
to knock...@googlegroups.com
I am writing some code that needs to know when an observable is read and/or change.  So I was thinking of making some modifications to the ko.numericObservable method described here to set a flag when the observable is accessed either for read or write something like:

ko.accessedObservable = function(initialValue) {

    var _actual = ko.observable(initialValue);

    var result = ko.dependentObservable({
        read: function() {
        // Mark a flag it has been read

            return _actual();
        },
        write: function(newValue) {
        // Mark a flag it has been written
            _actual(newValue);
        }
    });

    return result;
};

I have many javascript objects that has a bunch of nested properties (not known at design time) and objects therefore I am using the mapping plugin to make all the nested properties observable.  I have trying to get an idea of how to use "create" hooks to change the default functionality of the mapping plugin to make the accessedObservable instead of the default observable.  First off, do you think I am taking the correct approach to get notified of the read of the value?  Second, if I am taking the correct approach then can you explain how to use the create hooks to change the observable to accessedObservable?  I have been racking my brains all day and not getting very far.

rpn

unread,
Oct 9, 2011, 12:22:43 AM10/9/11
to knock...@googlegroups.com
I think that your approach sounds okay.  There is one thing that may or may not be what you expect: dependentObservables only call their "read' function when the value actually changes.  Subsequent calls will return a cached value.  So, if you are binding to the same dependentObservable multiple times or if a template is getting re-rendered that contains a dependentObservable the read function is not called.  Not sure if that matches your expectations/needs or not.  Otherwise, you would have to just make it a function that returns your value (and writes it, if more than one param is passed) rather than a dependentObservable.

As far as using the create callback, there are several ways to go.  You could create a constructor function and call it from the create callback for some part of your view model.  You could just return the appropriate object from the create callback (like http://jsfiddle.net/rniemeyer/6nxtM/)  or you could call ko.mapping.fromJS in the create callback passing options.data and then replace the part that you want to change with your custom observable.  Let me know if you need more help.

Francesco Abbruzzese

unread,
Oct 9, 2011, 2:40:52 AM10/9/11
to KnockoutJS
I think that the real point here is that the usual bindings used to
receive a value from the user, that is Value binding Checked binding,
and SelectedOptions binding are not aware of the data type in the
ViewModel. The NumericBinding just solve a small part of this general
problem. Every thing can be fixed once and for all by adding a new
attribute that contains the DataType to be used to all this bindings,
so that conversion of the string inserted by the user can take place
in the right way. It will be nice also an optional format attribute
that contains a format string to be used when the ViewModel value is
converted into a string.

I implementedd a similar solution in my Asp.net Mvc helpers for the
knockout library(http://mvccontrolstoolkit.codeplex.com/), and I take
the tatatype from the underlying .Net datatype. However I think, it
will be nice adding the DataType attribute in the knockout library
itself.

bruin...@gmail.com

unread,
Oct 10, 2011, 7:07:18 AM10/10/11
to knock...@googlegroups.com
Oh that's not good if the read returns a cached value.  That isn't good enough for my needs.  hmmm, any other ideas of how I could extend knockout so that I can detect when a value is read and written?

Thanks a bunch for your expertise.

rpn

unread,
Oct 10, 2011, 9:48:19 AM10/10/11
to knock...@googlegroups.com
Maybe something like this: http://jsfiddle.net/rniemeyer/unBUU/.  The reads/writes don't need to be observables.  I just did that so the UI could update.  Also note that when you edit a value in an input it writes to the observable, which makes it get re-read by the binding.  So, when you write you will get two reads in the sample (one for the input and one for the div).

bruin...@gmail.com

unread,
Oct 10, 2011, 10:37:29 AM10/10/11
to knock...@googlegroups.com
hmmm, it looks like I am barking up the wrong tree.  I have put together a sample of what you suggested (thanks by the way) and found that the read event is fired as soon as the view model marks it as my custom observable.  Then it will not be fired until the user modifies the property and the write and read event will be fired because it uses the cached value as you mentioned in the previous post. 

This isn't what I am looking for because a have a complex object with many properties and nested objects.  Some of these properties may be bound and others may not.  It is not known until runtime.  I was planning on marking all of the properties as  observables so that the UI could "applybinding" to whichever property it needs to at run time.  I only can send the properties that have been displayed in the UI. 

So I guess what I am really looking for is there a way to find out if a property is actually bound to the UI?  To recap, all the properties in the viewmodel are set up to be observable but only a subset of those properties will actually be bound to HTML UI controls. Is there a way looking at the viewmodel object to determine if the properties are bound to an HTML control?

Thanks again,

rpn

unread,
Oct 10, 2011, 11:21:53 AM10/10/11
to knock...@googlegroups.com
Take a look at this one:  http://jsfiddle.net/rniemeyer/8ypRz/.  Maybe you can re-create your scenario in a fiddle, if this doesn't do what you want.

bruin...@gmail.com

unread,
Oct 11, 2011, 10:04:48 AM10/11/11
to knock...@googlegroups.com
Thanks, I built on that and was able to get close enough. 

One last question for you.  Is there a good way to search the jsfiddle.net web site to look for the examples that are finding?  It would be great if I could be searching the site to be able see solutions that others have posted.  Thanks

Kris

unread,
Oct 11, 2011, 1:36:53 PM10/11/11
to KnockoutJS
bruins1: you can always do search in Bing or Google with the directed
search. For example to see all postings already crowed by rniemeyer
you would search with "site:jsfiddle.net rniemeyer", you can do the
same with any terms you are interested of.

Thanks,
Kris

simon.g...@dmap.com.au

unread,
Aug 20, 2013, 2:49:11 AM8/20/13
to knock...@googlegroups.com, cras...@gmail.com
Is this possible with the ES5 shim (http://blog.stevensanderson.com/2013/05/20/knockout-es5-a-plugin-to-simplify-your-syntax/) ? I've had absolutely zero luck trying to do the same but with ES5.
Reply all
Reply to author
Forward
0 new messages