I. Controllers are singletons
Controllers in Ember are singletons. When the user leaves a page and goes to another one, the controller is not torn down. It lives on, keeping its properties. This makes sense for a framework that aims to create long-lived, rich client-side applications, but it’s something to watch out for when developing Ember applications.
II. Understanding the problem
For example, let’s consider a controller ChartController
with a property changedCalculation
, which indicates whether the calculation of the chart has changed. If changedCalculation
is true, an Apply
button is displayed below the input for this property.
changedCalculation: function () {
this.set('controller.changedCalculation', true);
}
{{#if changedCalculation}}
<button class="btn btn-primary size-mini btn-ctrl pull-right" {{action 'appyCalculation'}}>
{{i18n js.charts.daten_tab.insert}}
</button>
{{/if}}
During a transition between two charts, if the chart object is changed and consequently any data bound to the chart (including the changedCalculation
property of the ChartController
) is rerendered, but since changedCalculation
is not changed, unrelated data will stay unchanged on the screen with the Apply
button still visible.
III. How to fix
Here are some solutions depending on the specific case:
- setupController: A hook you can use to set up the controller for the current route. This method is called with the controller for the current route and the model supplied by the model hook.
- resetController: A hook you can use to reset controller values either when the model changes or the route is exiting. (It has existed from Ember 1.7).
- deactivate: This hook is executed when the router completely exits this route. It is not executed when the model for the route changes.
Example:
setupController: function(controller, model) {
controller.set('changedCalculation', false);
this._super.apply(this, arguments);
}
IV. What we can do
The render
helper renders a combination of a controller and template, and optionally allows you to provide a specific model to be set to the content property of the controller. If you do not provide a model, the singleton instance of the controller will be used.
Example:
{{render 'follow-authors'}}
loadData: Ember.on('init', function() {
this.get('store').query('author', {
type: 'sugget_authors'
}).then((authors) => {
this.set('authors', authors);
});
})
In this example, the data of the authors
property only loads once during the initial rendering.
Source:
Public comments are closed, but I love hearing from readers. Feel free to contact me with your thoughts.