javascript - Multiple outlets in Ember.js v2 router - Stack Overflow

I'm just getting started with Ember.js and one thing that seems promising is the idea of multiple

I'm just getting started with Ember.js and one thing that seems promising is the idea of multiple outlets bining multiple templates mixed together to produce a plex but modular layout.

I can'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 "v2" 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.

Here's what I've read:

  • everything under the Routing guide (up to date, but not exhaustive)
  • "outlet" template helper api reference (this may be out of date? Every attempt I've made to call controller.connectOutlet() fails with Uncaught TypeError: Object <(generated animals.cats controller):ember170> has no method 'connectOutlet'.
  • announcement of Ember.js Router API v2. Specifically the bottom couple ments (question and answer on multiple outlets). Yes, this gist is marked "Warning; outdated; for up-to-date information see the routing guide". But the current routing guide doesn't seem to pletely 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't figure out how to connect additional outlets or instantiate additional templates.

What does work for me:

  • Setting up nested routes (well, nested resources; you can'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.

What I have not been able to figure out how to acplish:

  • 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'm trying to do is use a template as a mixin that I can embed wherever else I want.)

The thing that seems promising but fails for me is

  • Override a route's controller (extend the route using App.WhateverRoute = Ember.Route.extend(), supply my own setupController method) and call controller.connectOutlet here. This fails as described above; the controller object passed into this method does not have a connectOutlet method.

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):

<!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=".9.0/jquery.min.js"></script>
    <script src=".js/1.0.rc.2/dist/handlebars.js"></script>
    <script src=".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">
      <!-- you will not see this unless you disable App.AnimalsIndexRoute redirect. -->
      <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) {
          // BUG: this controller object has no connectOutlet method
          // (unment to see this yourself)
          // controller.connectOutlet('animal_mixin');
        }
      });
      App.initialize();
    </script>

</html>

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 "inheritance" provided by the nesting structure: the contents of animal_mixin could go directly in the "animals" template, and I wouldn't need to mention it in animals/cats and animals/dogs. That would be fine if I wanted it in all animals, but let's say I had another subroute of /animals that I don't want to include this snippet. Again, the example is contrived but I hope the question and the intent are clear.

I'm just getting started with Ember.js and one thing that seems promising is the idea of multiple outlets bining multiple templates mixed together to produce a plex but modular layout.

I can'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 "v2" 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.

Here's what I've read:

  • everything under the Routing guide (up to date, but not exhaustive)
  • "outlet" template helper api reference (this may be out of date? Every attempt I've made to call controller.connectOutlet() fails with Uncaught TypeError: Object <(generated animals.cats controller):ember170> has no method 'connectOutlet'.
  • announcement of Ember.js Router API v2. Specifically the bottom couple ments (question and answer on multiple outlets). Yes, this gist is marked "Warning; outdated; for up-to-date information see the routing guide". But the current routing guide doesn't seem to pletely 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't figure out how to connect additional outlets or instantiate additional templates.

What does work for me:

  • Setting up nested routes (well, nested resources; you can'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.

What I have not been able to figure out how to acplish:

  • 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'm trying to do is use a template as a mixin that I can embed wherever else I want.)

The thing that seems promising but fails for me is

  • Override a route's controller (extend the route using App.WhateverRoute = Ember.Route.extend(), supply my own setupController method) and call controller.connectOutlet here. This fails as described above; the controller object passed into this method does not have a connectOutlet method.

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):

<!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./ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    <script src="https://raw.github./wycats/handlebars.js/1.0.rc.2/dist/handlebars.js"></script>
    <script src="https://raw.github./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">
      <!-- you will not see this unless you disable App.AnimalsIndexRoute redirect. -->
      <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) {
          // BUG: this controller object has no connectOutlet method
          // (unment to see this yourself)
          // controller.connectOutlet('animal_mixin');
        }
      });
      App.initialize();
    </script>

</html>

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 "inheritance" provided by the nesting structure: the contents of animal_mixin could go directly in the "animals" template, and I wouldn't need to mention it in animals/cats and animals/dogs. That would be fine if I wanted it in all animals, but let's say I had another subroute of /animals that I don't want to include this snippet. Again, the example is contrived but I hope the question and the intent are clear.

Share Improve this question edited Jan 25, 2013 at 23:35 metamatt asked Jan 25, 2013 at 23:28 metamattmetamatt 14.5k7 gold badges49 silver badges57 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

You can use multiple named outlets. Here's a jsfiddle example: http://jsfiddle/W2dE4/6/.

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

Also see this answer for some other techniques.

events: {
    showModal: function(){
        this.render('modal', {
            into: 'index',
            outlet: 'modalOutlet',
            controller: this.controllerFor('modal')
        }); 
    }
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744700055a4588725.html

相关推荐

  • javascript - Multiple outlets in Ember.js v2 router - Stack Overflow

    I'm just getting started with Ember.js and one thing that seems promising is the idea of multiple

    1天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信