Knockout.js Custom Money Binding

EDIT: I think I've found a better solution. Click here to see the post on creating a money observable.

As I've been digging deeper into knockout.js, I had a need to simplify some things. I needed to have my view model hold float values but display it as a formatted money value. Time to write my own custom binding for knockout.

I'm a bit mixed about this. On one hand, it was dead simple to get the behavior I needed. On the other, the semantics don't match up. The built in bindings are things like text and value. That is, you are mating an object to the text or value property of a DOM element. DOM elements don't have a 'money' property, which makes this approach feel wrong.

There it is and I'm not confident that I'm using the tool appropriately. What do you think?

7 Comments so far

  1. Jared @ May 2nd, 2011

    If I were someone that would have to work on this code I would prefer the normal binding syntax for 2 reasons:

    1) It’s clear to me that your intent is to bind the .text() of the span to the Cash property of you vm. Using a custom binding doesn’t make that clear enough, I’d have to poke in the code to know what this was intended to do.

    2) It’s less code I’d have to maintain.

    I think you’re solution is a great tutorial for custom bindings in KO – something I didn’t know could be done to be honest – but I don’t think it is clearer than the default in this case.

    As an aside I thought the code that walks the money input backwards to put the commas in the appropriate place was smart. I liked the use of $.map (another thing I didn’t know about).

  2. josh @ May 2nd, 2011

    @Jared The main reason for the binding was to be able to have the display formatted, but the backing object stored as a float. I couldn’t really see how to do that without the custom binding. I’m hoping I can get some knockout.js experts to chime in here.

  3. Michael Smith @ May 2nd, 2011

    You might want to consider a writable dependent observable. On the read you could add your formatting and on the write you could strip out the formatting and set the backend observable.

  4. Michael Smith @ May 2nd, 2011
  5. josh @ May 2nd, 2011

    @Michael Thanks! I’m not sure how I missed this whole piece of functionality (read/write) in ko. I guess I’ll be pushing a new blog post to correct my implementation. 🙂

  6. Ryan Niemeyer @ May 2nd, 2011

    Personally, I don’t have a huge problem with using bindings in this manner. Anytime that you need to connect your view model with elements on the page, a binding handler is the way to go. I don’t feel that the binding needs to map directly to attributes on the element either. A common example is initializing an element to be a jQuery UI widget through a binding handler.

    However, if what you really are after is a way to format/deformat your view model values to/from the UI, then a writable dependentObservable would be a good choice. This way you can write just your formatting logic and leave the rest up to the existing text/value bindings. The other part to your binding is the CSS classes, but it seems like they could be added via the CSS binding without much problem.

    I look forward to more Knockout posts from you!

  7. ken @ October 4th, 2011

    I’m a ko rookie. I think the problem is that ko is lacking value types. One can delegate validation to a tool like http://docs.jquery.com/Plugins/Validation

    In a Save-less UI, one could write:
    vm.X.subscribe(function(newVal) {
    var validator = $(“#myForm”).validate();
    var isValid = validator.element(“#myField”);
    if (! isValid) return;
    // do ajax
    });

    Writing this for every field is a hassle. Does the event binder support valuechanged?

    I guess I need to write a valueVS binder: value + Validate + Save. I need to make this work w/ an inplace editor too. If only coding was easier 🙂

Leave a reply