{"id":1490,"date":"2022-08-30T15:16:58","date_gmt":"2022-08-30T15:16:58","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/23\/multiple-outlets-in-ember-js-v2-router-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:16:58","modified_gmt":"2022-08-30T15:16:58","slug":"multiple-outlets-in-ember-js-v2-router-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/multiple-outlets-in-ember-js-v2-router-collection-of-common-programming-errors\/","title":{"rendered":"Multiple outlets in Ember.js v2 router-Collection of common programming errors"},"content":{"rendered":"<p>I&#8217;m just getting started with Ember.js and one thing that seems promising is the idea of multiple outlets combining multiple templates mixed together to produce a complex but modular layout.<\/p>\n<p>I can&#8217;t get it to work, though. It seems like there were many questions, answers, and examples on this a few months ago (mid 2012) but in the march to 1.0 they very recently (December 2012\/January 2013) rewrote the router to a &#8220;v2&#8221; API. The docs are good at what they do describe but omit a lot of big picture context, and I have yet to find a single end-to-end example.<\/p>\n<p>Here&#8217;s what I&#8217;ve read:<\/p>\n<ul>\n<li>everything under the Routing guide (up to date, but not exhaustive)<\/li>\n<li>&#8220;outlet&#8221; template helper api reference (this may be out of date? Every attempt I&#8217;ve made to call <code>controller.connectOutlet()<\/code> fails with <code>Uncaught TypeError: Object has no method 'connectOutlet'<\/code>.<\/li>\n<li>announcement of Ember.js Router API v2. Specifically the bottom couple comments (question and answer on multiple outlets). Yes, this gist is marked &#8220;Warning; outdated; for up-to-date information see the routing guide&#8221;. But the current routing guide doesn&#8217;t seem to completely describe the behavior. The Rendering a template section of the guide shows how to render to different outlets that already exist (and I can get this to work), but I can&#8217;t figure out how to connect additional outlets or instantiate additional templates.<\/li>\n<\/ul>\n<p>What does work for me:<\/p>\n<ul>\n<li>Setting up nested routes (well, nested resources; you can&#8217;t nest routes; but you can customize routes for the nested resources), and nesting templates and outlets that are automatically instantiated according to the routes.<\/li>\n<\/ul>\n<p>What I have not been able to figure out how to accomplish:<\/p>\n<ul>\n<li>Manually instantiate templates and connect them to outlets. This seems necessary if you want to use multiple outlets, or if you want to have a structure your outlet\/template relationships differently than your routes. (There will be an example of this below. Essentially what I&#8217;m trying to do is use a template as a mixin that I can embed wherever else I want.)<\/li>\n<\/ul>\n<p>The thing that seems promising but fails for me is<\/p>\n<ul>\n<li>Override a route&#8217;s controller (extend the route using <code>App.WhateverRoute = Ember.Route.extend()<\/code>, supply my own <code>setupController<\/code> method) and call <code>controller.connectOutlet<\/code> here. This fails as described above; the controller object passed into this method does not have a <code>connectOutlet<\/code> method.<\/li>\n<\/ul>\n<p>Example (here as a jsFiddle, or below as a self-contained html document which embeds the CSS and scripts and loads Ember and dependencies from https links, so you should be able to just save to a local file and open in a browser if you want to try it):<\/p>\n<pre><code>\n\n  \n    Ember.js Router Example\n    \n      .outlet {\n        border: 1px solid black;\n        padding: 5px;\n      }\n    \n  \n\n  \n\n    \n    \n    \n\n\n    \n      <br \/>Root index template. You should not see this because we redirect App.IndexRoute elsewhere.<br \/><br \/>\n    \n\n    \n      <br \/>About this demo.<br \/><br \/>\n    \n\n    \n      <br \/>Guide to this demo.<br \/><br \/>\n    \n\n   \n      <br \/>Animals. You have selected:<br \/><br \/>\n      {{ outlet }}\n    \n\n    \n      \n      <br \/>No animal selected.<br \/><br \/>\n    \n\n    \n      <br \/>Cat. I can meow. Like all animals, I\n        {{ outlet }}\n      <br \/><br \/>\n    \n\n    \n      <br \/>Dog. I can bark. Like all animals, I\n        {{ outlet }}\n      <br \/><br \/>\n    \n\n    \n      <br \/>am alive.<br \/><br \/>\n    \n\n    \n      \n        <br \/>\n          Select contents for my outlet:\n          {{#linkTo \"index\"}}\/ (root){{\/linkTo}}\n          {{#linkTo \"about\"}}\/about{{\/linkTo}}\n          {{#linkTo \"guide\"}}\/guide{{\/linkTo}}\n          {{#linkTo \"animals\"}}\/animals{{\/linkTo}}\n          {{#linkTo \"animals.cats\"}}\/animals\/cats{{\/linkTo}}\n          {{#linkTo \"animals.dogs\"}}\/animals\/dogs{{\/linkTo}}\n        <br \/><br \/>\n\n        \n          {{ outlet }}\n        \n      \n    \n\n    \n      App = Ember.Application.create();\n      App.Router.map(function() {\n        this.resource(\"about\");\n        this.resource(\"guide\");\n        this.resource(\"animals\", function() {\n          this.route(\"cats\");\n          this.route(\"dogs\");\n        })\n      });\n      App.IndexRoute = Ember.Route.extend({\n        redirect: function() {\n          this.transitionTo('about');\n        }\n      });\n      App.AnimalsIndexRoute = Ember.Route.extend({\n        redirect: function() {\n          this.transitionTo('animals.cats');\n        }\n      });\n      App.AnimalsCatsRoute = Ember.Route.extend({\n        setupController: function(controller, model) {\n          \/\/ BUG: this controller object has no connectOutlet method\n          \/\/ (uncomment to see this yourself)\n          \/\/ controller.connectOutlet('animal_mixin');\n        }\n      });\n      App.initialize();\n    \n\n\n<\/code><\/pre>\n<p>Essentially animal_mixin is a chunk of boilerplate that I want to use repeatedly as a mixin, dropping it wherever I want by putting an outlet there and connecting it to this template. I realize this example is contrived, because I could do it with &#8220;inheritance&#8221; provided by the nesting structure: the contents of animal_mixin could go directly in the &#8220;animals&#8221; template, and I wouldn&#8217;t need to mention it in animals\/cats and animals\/dogs. That would be fine if I wanted it in all animals, but let&#8217;s say I had another subroute of \/animals that I don&#8217;t want to include this snippet. Again, the example is contrived but I hope the question and the intent are clear.<\/p>\n<ol>\n<li>\n<p>You can use multiple named outlets. Here&#8217;s a jsfiddle example: http:\/\/jsfiddle.net\/W2dE4\/6\/.<\/p>\n<pre><code>\n    {{outlet header}}\n    {{outlet body}}\n    {{outlet navBar}}\n\n<\/code><\/pre>\n<p>Also see this answer for some other techniques.<\/p>\n<pre><code>events: {\n    showModal: function(){\n        this.render('modal', {\n            into: 'index',\n            outlet: 'modalOutlet',\n            controller: this.controllerFor('modal')\n        }); \n    }\n}\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-23 09:50:46. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I&#8217;m just getting started with Ember.js and one thing that seems promising is the idea of multiple outlets combining multiple templates mixed together to produce a complex but modular layout. I can&#8217;t get it to work, though. It seems like there were many questions, answers, and examples on this a few months ago (mid 2012) [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1490","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/1490","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=1490"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/1490\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=1490"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=1490"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=1490"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}