I'm just starting out with Ember.js, and one thing that seems promising is the idea of several outlets combining several templates mixed together to create a complex but modular layout.
I can not make it work. It seems that there were a lot of questions, answers and examples about this a few months ago (in mid-2012), but in March, before 1.0, they most recently (December 2012 / January 2013) rewrote the router on the "v2" API. Documents are good in what they describe, but they omit a lot of the large context of the picture, and I still have to find one cross-cutting example.
Here is what I read:
- everything under the Routing Guide (updated but not exhaustive)
- the "hello api reference" link in the form of a template (can this be deprecated? Every attempt I made to call
controller.connectOutlet() fails Uncaught TypeError: Object <(generated animals.cats controller):ember170> has no method 'connectOutlet' . - Ember.js Router API v2 Announcement In particular, the bottom pair of comments (question and answer to several outlets). Yes, this value is marked "Warning, deprecated, see the Routing Guide for the latest information." But the current routing guide does not seem to fully describe the behavior. The Rendering section of the template in the manual shows how to visualize the various releases that already exist (and I can make it work), but I may not figure out how to connect additional outputs or create additional templates.
What works for me:
- Configuring nested routes (well, nested resources, you cannot embed routes, but you can configure routes for nested resources) and nested templates and outputs that are automatically created according to the routes.
What I could not figure out how to do this:
- Manually create templates and connect them to the outputs. This seems necessary if you want to use several outlets, or if you want the structure of your links / templates to be structured differently than your routes. (The following is an example of this. Essentially, I'm trying to use a template like mixin, which I can embed anywhere I want.)
What seems promising, but not for me, is
- Override the route controller (extend the route using
App.WhateverRoute = Ember.Route.extend() , put my own setupController method) and call controller.connectOutlet here. This is not performed as described above; The controller object passed to this method does not have a connectOutlet method.
Example ( here as jsFiddle or lower as a self-contained html document that inserts CSS and scripts and loads Ember and https dependencies, so you can just save it in a local file and open it in the browser if you want to try it):
<!DOCTYPE html> <html lang="en"> <head> <title>Ember.js Router Example</title> <style> .outlet { border: 1px solid black; padding: 5px; } </style> </head> <body> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <script src="https://raw.github.com/wycats/handlebars.js/1.0.rc.2/dist/handlebars.js"></script> <script src="https://raw.github.com/emberjs/ember.js/release-builds/ember-1.0.0-pre.4.js"></script> <script type="text/x-handlebars" data-template-name="index"> <p>Root index template. You should not see this because we redirect App.IndexRoute elsewhere.</p> </script> <script type="text/x-handlebars" data-template-name="about"> <p>About this demo.</p> </script> <script type="text/x-handlebars" data-template-name="guide"> <p>Guide to this demo.</p> </script> <script type="text/x-handlebars" data-template-name="animals"> <p>Animals. You have selected:</p> <div class='outlet'>{{ outlet }}</div> </script> <script type="text/x-handlebars" data-template-name="animals/index"> <p>No animal selected.</p> </script> <script type="text/x-handlebars" data-template-name="animals/cats"> <p>Cat. I can meow. Like all animals, I <span class='outlet'>{{ outlet }}</span> </p> </script> <script type="text/x-handlebars" data-template-name="animals/dogs"> <p>Dog. I can bark. Like all animals, I <span class='outlet'>{{ outlet }}</span> </p> </script> <script type="text/x-handlebars" data-template-name="animal_mixin"> <p>am alive.</p> </script> <script type="text/x-handlebars" data-template-name="application"> <div class="container"> <p> Select contents for my outlet: {{#linkTo "index"}}/ (root){{/linkTo}} {{#linkTo "about"}}/about{{/linkTo}} {{#linkTo "guide"}}/guide{{/linkTo}} {{#linkTo "animals"}}/animals{{/linkTo}} {{#linkTo "animals.cats"}}/animals/cats{{/linkTo}} {{#linkTo "animals.dogs"}}/animals/dogs{{/linkTo}} </p> <div class='outlet'> {{ outlet }} </div> </div> </script> <script> App = Ember.Application.create(); App.Router.map(function() { this.resource("about"); this.resource("guide"); this.resource("animals", function() { this.route("cats"); this.route("dogs"); }) }); App.IndexRoute = Ember.Route.extend({ redirect: function() { this.transitionTo('about'); } }); App.AnimalsIndexRoute = Ember.Route.extend({ redirect: function() { this.transitionTo('animals.cats'); } }); App.AnimalsCatsRoute = Ember.Route.extend({ setupController: function(controller, model) { </script> </html>
In essence, animal_mixin is a piece of the template that I want to reuse as mixin, discarding it wherever I want, placing the output there and connecting it to this template. I understand that this example is contrived because I could do it with the “inheritance” provided by the nesting structure: the contents of animal_mixin could go directly to the “animals” template, and I didn’t have to mention this in animals / cats and animals / dogs. It would be nice if I wanted this for all animals, but let me say that I have other routines / animals that I do not want to include this fragment. Again, an example is contrived, but I hope that the question and intention are clear.
source share