Reputation: 9082
When a view's template is refreshed due to changes of the model, the didInsertElement
hook is not triggered as Ember tries to reuse views as much as possible. This causes some problems for me in that I need to select the first element of a list when the template is rerendered. This happens, for example, when new data is loaded from the server or the application transitions to a different route.
The odd thing is that the view's init
method does get called when the application transitions to a different route. The issue is that the template hasn't been rendered at that point, that is, the view hasn't been populated with the new contents of the controller.
In short, how can I be notified after the template of a view has finished rerendering so that I can manipulate the view's contents?
For your information, observing the controller's model is not an option either as the view hasn't been updated by the time the callback is fired.
<script type="text/x-handlebars" id="list">
<div>
<ul>
{{#each model.items}}
<li class="item">
<p>{{title}}</p>
</li>
{{/each}}
</ul>
</div>
</script>
Update The view needs to be notified when the each
block is rerendered. I wanted to use the solution in this question, but it seems that only the each
block is rerendered and not the entire template (which is what I want). I could add a trigger event in the each block, but that is very expensive as the custom event would be triggered in each loop of the each
block.
Upvotes: 1
Views: 378
Reputation: 19128
Maybe this could work:
App.ListView = Ember.View.extend({
templateName: 'list',
contentChanged: function() {
Ember.run.scheduleOnce('afterRender', this, 'selectFirstElement')
}.observes('controller.content.[]'),
selectFirstElement: function() {
// for simplicity
this.$('li:first').addClass('selected');
}
});
Using observes('controller.content.[]')
make the contentChanged
function be called, if some change is performed in the controller content. To don't get that function called a lot of times in the same runloop we use the Ember.run.scheduleOnce('afterRender', ...)
, so selectFirstElement
is called just once, and because it's scheduled in the afterRender
queue, you can manipule the dom.
Live demo http://jsfiddle.net/marciojunior/4b2V3/
Upvotes: 4
Reputation: 536
App.MagicView = Ember.View.extend({
doMagic: function() {
// magic goes here
}.on('didInsertElement');
});
Update: I see now. Here's my brain dump: http://emberjs.jsbin.com/URidoBi/3/edit. Not the cleanest way, but should get you around the problem.
Upvotes: 0