ember-time
ember-time copied to clipboard
Wanted to share our solution
Thanks so much for this example. Here is what our solution looks like in coffeescript with jasmine tests. Note: we load moment
onto Ember
rather than window, hence Ember.moment
.
from_now_view.js.coffee
:
App.FromNowView = Ember.View.extend
TICK_DELAY: 5000
classNames: 'timestamp'
template: Ember.Handlebars.compile('{{view.output}}')
output: (-> Ember.moment(@get('value')).fromNow() ).property('value')
didInsertElement: -> @tick()
tick: -> @nextTick = Ember.run.later @, @tock, @TICK_DELAY
tock: ->
@notifyPropertyChange 'value'
@tick()
willDestroyElement: -> Ember.run.cancel @nextTick
from_now_view_spec.js.coffee
:
describe 'FromNowView', ->
model = view = null
beforeEach ->
model = Em.Object.create createdAt: Date.now()
view = App.FromNowView.create valueBinding: 'model.createdAt'
describe 'output property', ->
it 'outputs moment fromNow', ->
expect(view.get 'output').toBe('a few seconds ago')
describe '#didInsertElement', ->
it 'starts ticking', ->
spyOn view, 'tick'
view.didInsertElement()
expect(view.tick).toHaveBeenCalled()
describe '#tick', ->
it 'tocks', ->
spyOn Ember.run, 'later'
view.tick()
expect(Ember.run.later).toHaveBeenCalledWith(view, view.tock, view.TICK_DELAY)
describe '#tock', ->
it 'touches the value', ->
spyOn view, 'notifyPropertyChange'
view.tock()
expect(view.notifyPropertyChange).toHaveBeenCalledWith('value')
it 'ticks', ->
spyOn view, 'tick'
view.tock()
expect(view.tick).toHaveBeenCalled()
describe '#willDestroyElement', ->
it 'stops ticking', ->
spyOn Ember.run, 'cancel'
view.nextTick = 'abc'
view.willDestroyElement()
expect(Ember.run.cancel).toHaveBeenCalledWith('abc')
This is awesome, and a very detailed spec. I know the Ember team favour QUnit, but I still love Jasmine for its readability.
This repo/post was written before components were introduced, but now it seems exactly the sort of thing you’d create a {{from-now}}
component for.
Yep, definitely will implement this as a component now. Thanks for the example!
One thing I've found a need for is to be able to recalculate a computed property when certain time events occur, like when the date rolls over to the next day (because the computed property does calculations based on the current date). I think I can leverage some of this for that purpose. I can put the logic on the application controller and use needs
to "inject" the current time computed where I, well, need it.
@neverfox I know a few folks have implemented a clock
service and injected it wherever it’s needed. It’s essentially the same as what your propose. Would love to see your implementation. It’s a pattern worth documenting.