2
votes

I'm looping through a content of an ArrayController whose content is set to a RecordArray. Each record is DS.Model, say Client

{{# each item in controller}}
{{item.balance}}
{{/each}}

balance is a property of the Client model and a call to item.balance will fetch the property from the model directly. I want to apply some formatting to balance to display in a money format. The easy way to do this is to add a computed property, balanceMoney, to the Client object and do the formatting there:

App.Client = DS.Model({
 balance: DS.attr('balance'),

 balanceMoney: function() {
   // format the balance property
   return Money.format(this.get('balance');
 }.property('balance')
});

This serves well the purpose, the right place for balanceMoney computed property though, is the client controller rather than the client model. I was under the impression that Ember lookup properties in the controller first and then tries to retrieve them in the model if nothing has been found. None of this happen here though, a call to item.balanceMoney will just be ignored and will never reach the controller.

Is it possible to configure somehow a controller to act always as a proxy to the model in all circumstances.

UPDATE - Using the latest version from emberjs master repository you can configure the array controller to resolve records' methods through a controller proxy by overriding the lookupItemController method in the ArrayController. The method should return the name of the controller without the 'controller' suffix i.e. client instead of clientController. Merely setting the itemControllerClass property in the array controller doesn't seem to work for the moment.

lookupItemController: function( object ) {
        return 'client';
    },
2

2 Answers

2
votes

This was recently added to master: https://github.com/emberjs/ember.js/commit/2a75cacc30c8d02acc83094b47ae8a6900c0975b

As of this writing it is not in any released versions. It will mostly likely be part of 1.0.0.pre.3.

1
votes

If you're only after formatting, another possibility is to make a handlebars helper. You could implement your own {{formatMoney item.balance}} helper, for instance.

For something more general, I made this one to wrap an sprintf implementation (pick one of several out there):

Ember.Handlebars.registerHelper('sprintf', function (/*arbitrary number of arguments*/) {
    var options = arguments[arguments.length - 1],
        fmtStr = arguments[0],
        params = Array.prototype.slice.call(arguments, 1, -1);

    for (var i = 0; i < params.length; i++) {
        params[i] = this.get(params[i]);
    }

    return vsprintf(fmtStr, params);
});

And then you can do {{sprintf "$%.2f" item.balance}}.

However, the solution @luke-melia gave will be far more flexible--for example letting you calculate a balance in the controller, as opposed to simply formatting a single value.

EDIT:

A caveat I should have mentioned because it's not obvious: the above solution does not create a bound handlebars helper, so changes to the underlying model value won't be reflected. There's supposed to be a registerBoundHelper already committed to Ember.js which would fix this, but that too is not released yet.