Justin Lynch
Justin Lynch

Reputation: 3

How do you update a controller from another controller in ember.js?

In my application I have common header that outlets into the main application layout. In that header you can select a site. I need that site selection to update another template that is rendered in the application layout. Having struggled with this for a few days I think the correct way to solve this is to use a shared service, to have the header controller observe the site selection and set that value in the shared service, then to have the index controller use a Ember.computed.alias on the value in the service controller. The following is an example of my code:

controllers/header.js

import Ember from 'ember';

export default Ember.Controller.extend({
  sessionService: Ember.inject.service(),

  currentSiteChanged: Ember.observer('session.current_site', function(){
    var current_site = this.get('session.current_site');
    console.log('currentSiteObserver', current_site);
    this.get('sessionService').set('currentSite', current_site);
  }),

});

controllers/index.js

import Ember from 'ember';

export default Ember.Controller.extend({
  sessionService: Ember.inject.service(),
  currentSite: Ember.computed.alias('sessionService.currentSite'),
  dashboardData: function(){
    var currentSite = this.get('currentSite');
    console.log("in dashboardData", currentSite);
    //other code that uses the currentSite
  }.property('currentSite'),
});

services/session-service.js

import Ember from 'ember';

export default Ember.Service.extend({
  currentSite: null,

  setCurrentSite: function(){
    var currentSite = this.get('session.current_site');
    this.set('currentSite', currentSite );
  }.on('init'),
});

I think this should allow someone to select a site in the header and have the dashboardData property in index update to use that selection. When the page initially loads the header defaults to the first site and the index renders it has the correct site value that it must have gotten from the session-service, however if you select another site the index does not get updated. Via the console.logs and debugging I can see that the header is observing the change and setting the value on the session-service.

Additionally I have tried solving this other ways (injecting the header service into the index and observing a property, injecting the index in the header and directly setting the value, sending and listening to events,etc) but I am willing to try anything or to be corrected that this isn't the correct way to solve the problem.

I am using ember 1.13.8 and moving to 2 isn't an option at the moment.

Upvotes: 0

Views: 472

Answers (1)

Christopher Milne
Christopher Milne

Reputation: 938

I don't think a service is an appropriate solution to this problem.

You want your application to have a good RESTful url design (respect for urls is a corner-stone of the Ember framework), so try to capture your application state in the URL.

Consider that if a user were to select a site, and then hit refresh they would lose their selection unless you stored it somehow in a cookie or localStorage.

I would recommend using either routes or query parameters to solve your problem.

Routes
Using routes is fairly straightforward (http://whatever.com/sites/pet-hampsters).

Query Params
You can also use query params, something like this http://whatever.com/?site=pet%20hampsters.

To do this you would write an action that bubbles up to your application controller and sets the value of the 'site' queryParam. Any of your sub-controllers on the currently active route can then read the site value with the new Ember.inject syntax. This is the conventional way to manage dependencies between controllers.

Upvotes: 1

Related Questions