2

I'm working with Ember.Router, and one thing I can't figure out is how to bind objects to controllers that the Router is instantiating.

For instance, here is a controller class (extended) that the Router will instantiate for a specific route ('page'), as well as a controller object (created), say to handle user administration tasks on a part of the application outside of the Router:

// controller used by Router to render the "page" route
App.PageController = Em.ObjectController.extend({
    content: Em.Object.extend({
        foo: 'bar'
    })
});

// global controller for users
App.usersController = Em.ObjectController.extend({
    content: Em.Object.extend({
        fooBinding: App.PageController.foo
        // the above will not work since Em.Router
        // instantiates the page controller dynamically
    })
});

So when the router loads it will instantiate App.PageController into App.router.pageController, but that's after App.usersController is already created. So how can App.usersController access data in a controller that the Router is managing?

Any ideas?

sly7_7
  • 11,961
  • 3
  • 40
  • 54
Nathan Rutman
  • 2,215
  • 2
  • 21
  • 25
  • I have asked a [similar question](http://stackoverflow.com/questions/11301798/ember-js-how-to-properly-bind-a-collection-to-a-view-using-ember-router) that might help you if you're using ember-0.9.8.1, if you're using ember-latest there are some differences tho – MilkyWayJoe Jul 26 '12 at 02:18

1 Answers1

5

There are a few mistakes in your sample.

First, you should never directly setup a property with an Object value at declaration time: this value would be shared across all instances of the class. Here, it does not really matter, but it's a bad practice. In this case, the good way of setting up the PageController content is to bind it in router, at connectOutlet call, like that:

connectOutlets: function (router) {
  var theContainerController = router.get('theContainerController'),
      objectWithFooBar = Ember.Object.create({
    foo: 'bar'
  });
  theContainerController.connectOutlet('page', objectWithFooBar);
}

Second mistake is the naming of usersController: it should be UsersController, as it is a class, which will be injected in the router as usersController during initialize call. It seems also quite strange to have users pluralized & ObjectController. Certainly should be singularized...

Last, and certainly what will be the most interesting regarding the question, once you will have preceding remarks applied, you will be able to setup the binding using:

App.UserController = Em.ObjectController.extend({
  fooBinding: 'App.router.pageController.foo'
});

App.router can be setup before your call to App.initialize. It is definitively a bad coupling to have UserController using a global symbol to directly access to PageController, but it does the job in your case.

A definitely yet better solution would also be to bind UserController's content in a connectOutlet call.

Mike Aski
  • 9,180
  • 4
  • 46
  • 63
  • Mike, thanks for the info. So then, are you saying that when using the Router, all controllers should be instantiated with the router? I was trying to show an example of a controller being used with the router (PageController) and a global controller that would be active all the time (userController). The mistake was that I used .extend() for userController instead of .create(), which is confusing. – Nathan Rutman Jul 26 '12 at 15:26
  • In fact, yes, all controllers will be instanciated & injected in the router by the `App.initialize()` call. – Mike Aski Jul 26 '12 at 16:08
  • Mike, do you think your suggestions here can be seen as a possible solution to this: https://github.com/emberjs/ember.js/issues/1521, and the problem shown by this: http://jsfiddle.net/6p6XJ/79/. I didn't open the issue or create the fiddle but will not the less be interested in the solution. – brg Nov 13 '12 at 17:14