0

I'm trying to use an already instantiated controller in my ember route.

Is it not normal to ever have instantiated a controller and want to use that in a route? I know that if I the application instantiate a controller for me, I can then to router.get("myController") but that won't access one that I had instantiated myself.

How do I get the piece of code at the bottom of my router to work?

HTML

 <script type="text/x-handlebars" data-template-name="application">
    {{outlet}}
 </script>


<script type="text/x-handlebars" data-template-name="instanced">
    <h1>Hello from instanced template</h1>
    {{showinstancedvalue}}<hr>
    {{outlet}}
</script>


<script type="text/x-handlebars" data-template-name="foobar">
    <h1>hello from foobar</h1>
    {{foobarvalue}}
</script>

Javascript

var App = Ember.Application.create();
// application view and controller
App.ApplicationView = Ember.View.extend({
    templateName: 'application',
});
App.ApplicationController = Ember.Controller.extend();




// foobar controller and view
App.FoobarController = Ember.Controller.extend({
    foobarvalue: "working"
});
App.FoobarView = Ember.View.extend({
    templateName: 'foobar'
});



// instantiated controller and view
App.InstancedController = Ember.Controller.extend({});
App.instancedController = App.InstancedController.create({
    myvar: "a value from an instantiated controller"
});
App.InstancedView = Ember.View.extend({
    templateName: 'instanced',
});
App.instancedView = App.InstancedView.create({
    showinstancedvalueBinding: 'App.instancedController.myvar'
});

App.instancedView.append();

App.router = Ember.Router.create({
    enableLogging: true,
    root: Ember.Route.extend({
        index: Ember.Route.extend({
            route: '/',
            redirectsTo: 'works'
        }),
        works: Ember.Route.extend({
            route: '/works',
            connectOutlets: function(router) {
                router.get('applicationController').connectOutlet('foobar');
            }
        }),
        broken: Ember.Route.extend({
            route: '/broken',
            connectOutlets: function(router) {

                // no error in console, but foobar doesn't appear
                // router.get('instancedController').connectOutlet('foobar');

                // *** this one was my best guess as to what I thought would work ***
                // no error in console, but foobar doesn't appear
                // App.instancedController.connectOutlet('App.Foobar');

                // Uncaught Error: assertion failed: The name you supplied foobar did not resolve to a view FoobarView
                // App.instancedController.connectOutlet('foobar');
            }
        }),

    })
});

App.initialize(App.router);​
Johnny Bones
  • 8,786
  • 7
  • 52
  • 117
Hortitude
  • 13,638
  • 16
  • 58
  • 72

2 Answers2

3

Take a look at the connectOutlet definition, it includes a basic documentation as a comment so you can have a better understanding of how it's supposed to or and to be used.

Basically, you should really connect it to the applicationController, since the {{outlet}} sits on the ApplicationView template. In this scenario, the framework will find a view and controller that should be used in that state (in your case FoobarView and foobarController since it's specified with the argument 'foobar') and add to a collection (named controllers) inside the applicationController. If you try to connect directly to your instance of foobarController, it won't find a outlet on its view (which at that moment shouldn't be instantiated, I believe) AND you'd be saying to that controller "hey, find yourself, then connect yourself to you" kind of thing.

This could work if you had an outlet inside the foobar view template and you'd connect this outlet to something other than foobar (as a child state/route). So you should read more about the outlets and named outlets.

Additionally, I strongly recommend these links:

  • Router Primer - This article is about two weeks fresh, and it's apparently the best there is right now, make sure you read this one!
  • Ember.js Routing - the Director’s Cut - Step-by-Step post about the Router, make sure you read this one too.
  • Outlets - This is a bit old but is being mantained
  • JSFiddle Sample 1 - Sample Fiddle with routing you can use as reference
  • JSFiddle Sample 2 - Sample Fiddle with routing you can use as reference (this is newer than previous)
MilkyWayJoe
  • 9,082
  • 2
  • 38
  • 53
  • i updated the question to give a better idea of where I'm confused. I also updated the code to hopefully make it more clear too – Hortitude Nov 13 '12 at 23:31
  • It doesn't seem that much clear to me. What do you want to do? And why do you need to create an instance of that controller? and why are you creating the instance in the application? Ember does all of that that for you. If you could take some time to explain what you're trying to do, it would help a lot. If you want to have access to the controller in your code, you can always reference `App.router.get('controller.controllers.instancedController')` (or some path like that) to a variable and work with that reference. – MilkyWayJoe Nov 14 '12 at 15:18
  • Sorry if it isn't clearer. Thanks for taking the time to re-read. I don't have a particular use case that shows the need for this. I was actually just trying to learn and evaluate ember. It just seemed to me from what I had read in the getting started guide that it was a reasonable expectation to instantiate controllers. Perhaps I either misread or the guide doesn't necessarily outline practices for application building? – Hortitude Nov 16 '12 at 05:04
  • 1
    The documentation wasn't Ember's greatest strength for a while. It's getting better now. When you use `Ember.Router`, a lot of things work slight different: you don't instantiate any of your views or controllers, the framework does that for you. Another general convention that you have to follow is naming your objects: use `App.ThisIsAClass` when you're *defining the class* & `App.thisIsAClass` when accessing the *instance* while the app is running (Ember will create an instance with the same name cammelCased). There are other things you should know about. Follow the links.. they really help! – MilkyWayJoe Nov 16 '12 at 05:39
  • Basically the only thing you'd normally `create` is the instance of the App itself, all the other objects are attached to the app via `extend` and the App will create the instances when it needs them, as well as dispose them. Check the link to my samples in JSFiddle and you'll see how each piece (handlebars templates, views, models & controllers) connect together – MilkyWayJoe Nov 16 '12 at 05:47
  • Thanks. I had read the links, but was just trying to reconcile this against the other documentation (where it talks about instantiated controllers and views and connecting them). I really appreciate you taking the time to help! – Hortitude Nov 16 '12 at 14:35
  • both of jsfiddles seem to be broken (uncaught typeerror in Chrome) – Qrilka Mar 15 '13 at 06:20
1

You should try to elaborate on your requirements. This makes no sense from my point of view.

    broken: Ember.Route.extend({
        route: '/broken',
        connectOutlets: function(router) {
            App.foobarController.connectOutlet('foobar');
        }
    }),

This code just can't work, since you are invoking connectOutlet on your fooBarController. So it searches for {{outlet}} in the assigend view. But in the template named foobar you do not not have a {{outlet}} specified. And even if you fix that, it makes just no sense, since this line would try to connect an outlet with a new instance of Foobar View. So you basically have the FooBarView of your FooBarController and inside its view, you try to connect a outlet again with a new instance of FooBarView??

So without explanation of requirements this question cannot be answered.

mavilein
  • 11,648
  • 4
  • 43
  • 48
  • i updated the question to give a better idea of where I'm confused. I also updated the code to hopefully make it more clear too. – Hortitude Nov 13 '12 at 23:30
  • Like MilkyWayJoe i do not get the idea, what you are trying to achieve there. Instead of relying on the framework you are instantiating the InstancedController yourself. Why do you do this? Why not count on App.initialize()? I do not understand why you do this, but i guess the problem is that you are instantiating controllers not in a way Ember would do. Ember does not put them directly into the App, but rather into App.router. – mavilein Nov 15 '12 at 19:12
  • Like I commented for MilkyWayJoe, I was mostly trying to just learn and reconcile different documentation examples I saw. One area showed routers and another showed instantiating controllers and views. I think I understand now. Thanks for your help -- I really appreciate you taking the time. – Hortitude Nov 16 '12 at 14:36