The problem
I have a view which displays a list of workers. This view has a button which calls a controller method named refresh
. Originally I was setting the content
to this list, but noticed that the UI would flicker, which would be especially annoying once this is run on a timer.
I managed to make everything work without flickering using the following:
App.WorkersIndexController = Ember.ArrayController.extend
refresh: ->
console.log 'refreshing workers'
# set a property to a new collection
@set 'refreshing', App.Worker.find()
# observer that watches the new collection load
update: (->
refreshing = @get 'refreshing'
return unless refreshing.get('isLoaded')
# what this question is about...
Ember.run =>
@set 'content', refreshing
).observes('refreshing.isLoaded')
As you can see I'm setting the refreshed content to a temporary variable, and observing the loading of the content and then updating the content. The content flickered less until I added a call to Ember.run
which removed the flicker entirely.
I understand why the flicker is occurring, and I understand why Ember.run
makes it go away but my question is what is the best way to solve this without resorting to Ember.run
? I feel like calling Ember.run is kind of a last resort... Any help would be greatly appreciated!
Edit: Also I'm not using ember data. The find
method looks like this:
App.Worker.reopenClass
find: ->
console.log 'loading workers'
workers = Em.A []
request = $.getJSON '/api/admin/workers', (data) =>
console.log ' -> loaded workers'
data.forEach (d) =>
worker = App.Worker.create(d)
worker.set 'isLoaded', true
workers.pushObject(worker)
request.error =>
console.log ' -> failed to load workers'
workers.set 'isFailed', true
request.complete =>
workers.set 'isLoaded', true
workers
I have avoided flicker in similar situations by having a fixed list who's objects I just change.
In the simplest case, lets' say you were displaying names, and knew that you knew you'd never have more than 3 elements you could make
and have your template be
you could then add names by running
and update the list without any flicker. Only a single element in the list is changed at a time, so you don't have the flicker from the whole list being redrawn.
In practical terms you might need App.names to be an ArrayController so that you can handle expanding the list gracefully, but the gist of that will work.