BenjaminRH
BenjaminRH

Reputation: 12172

Automatically update Ember Handlebar helper when a ticker runs

I'm trying to do something like "timeago" which automatically updates itself in a view even though there isn't a bound value that's actually changing. To do this, I've got the following app-wide clock ticker thing which I inject into my controllers, like so:

// Setup an app-wide clock that can be depended on for updates every second or minute
App.Clock = Ember.Object.extend({
    second: null,
    minute: null,

    init: function () {
        this.tick(); // run once initially
        this.scheduler();
    },

    scheduler: function () {
        Ember.run.later(this, function () {
            this.tick();
            this.scheduler();
        }, 1000);
    },

    tick: function () {
        var now = new Date();

        this.setProperties({
            second: now.getSeconds(),
            minute: now.getMinutes(),
        });
    }
});

// Initialize it and inject it into our controllers
App.register('clock:main', App.Clock, { singleton: true });
App.inject('controller', 'clock', 'clock:main');

OK. Now I use that in a Handlebars helper. This is the bit I think I'm screwing up here:

Ember.Handlebars.registerBoundHelper('format-date', function (value) {
    return 'Testing: ' + this.get('clock.second');
}, 'clock.second');

And then I add it to the view, with something like {{format-date 'foo'}}. It displays the initial number (of seconds, from the clock) just fine, but doesn't update. I'd obviously like the clock to be bound in some way to the helper so that it updates automatically ever second, in this case. What am I missing?

EDIT: Most of the solutions for this suggest using a view. I'd like to do this without using a view. Ideally, I'd like to be able to use the helper like this:

Ember.Handlebars.registerBoundHelper('format-date', function (value) {
    return 'Testing: ' + this.get('clock.second');
}).property('clock.second');

Upvotes: 0

Views: 1026

Answers (1)

GJK
GJK

Reputation: 37369

I can't tell you why the helper you've written isn't updating. From what I can tell, you're using a valid syntax. But, I can tell you that this works for sure:

{{format-date date clock.second}}

Passing in the clock.second property tells Ember.js that the helper depends on that property. You can see it working here. I know it's an ugly hack, but it does work.

As for the code that you have, it should work, but doesn't. I'll look into it and possibly file a bug with Ember.js.

EDIT: It looks like this issue has been brought up before. To quote the documentation (emphasis mine):

The Ember.Handlebars.registerBoundHelper method takes a variable length third parameter which indicates extra dependencies on the passed in value.

So while the guide seems to be a bit vague, the docs are more definitive. It looks like you might be stuck with the hack above.

Or, if you want something a little more clever, I might try this:

var createDateProperty = function(dependentKey) {
    return function() {
        // I would use moment, you can use whatever you want
        return moment(this.get(dependentKey)).format('MMMM Do YYYY');
    }.property(dependentKey, 'clock.second');
};

Then, to use it:

App.FooBarController = Ember.ObjectController.extend({
    formattedBirthday: createDateProperty('birthday')
});

Then just use the property without a helper:

{{formattedBirthday}}

Upvotes: 1

Related Questions