问题描述
我刚刚开始使用Ember.js,而且有一点看起来很有希望的是将多个模板混合在一起的多个插座的想法,从而产生复杂但模块化的布局。
不过我不能让它上班。几个月前(2012年中期)似乎有很多问题,答案和例子,但是在最近(2012年12月/ 2013年1月)的1.0版中,将路由器重写为v2API。文档很好的描述了他们的描述,但省略了很多大图片的上下文,我还没有找到一个端到端的例子。
这是什么我已阅读:
- (这可能已经过时了)我试图调用
controller.connectOutlet( )
失败与未捕获TypeError:Object<(生成的animals.cats控制器):ember170>没有方法'connectOutlet'
。 - 公布,具体说下面的几个评论(问题是的,这个要点被标记为警告;过时;为了最新的通知参见路线指南。但目前的路由指南似乎没有完全描述这种行为。本指南的部分显示了如何向不同的网点呈现已经存在(而且我可以得到这个工作),但是我不知道如何连接其他插件或实例化其他模板。
对我有用的工作:
- 设置嵌套的路由(好的,嵌套的资源;你不能嵌套路由;但是你可以定制嵌套资源的路由),以及根据路由自动实例化的嵌套模板和插座。
我还没有能够弄清楚如何完成:
- 手动实例化模板并将其连接到插座。如果您想使用多个插座,或者想要使您的插座/模板关系与您的路线不同的结构,这似乎是必要的。 (下面将会有一个例子,本质上我正在做的是使用一个模板作为一个混合,我可以嵌入任何我想要的任何地方。)
似乎有希望但对我失败的事情是
- 覆盖路由的控制器(使用
App.WhateverRoute = Ember.Route.extend()
,提供我自己的setupController
方法),并调用controller.connectOutlet
这里。如上所述失败;传递给该方法的控制器对象没有connectOutlet
方法。
示例(或以下作为嵌入CSS的自包含html文档并且脚本和加载来自https链接的Ember和依赖项,所以您应该能够保存到本地文件并在浏览器中打开,如果您想尝试):
<!DOCTYPE html>
< html lang =en>
< head>
< title> Ember.js路由器示例< / 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-handlebarsdata-template-name =index>
< p>根索引模板。您不应该看到这一点,因为我们将App.IndexRoute重定向到其他位置。< / p>
< / script>
< script type =text / x-handlebarsdata-template-name =about>
< p>关于此演示。< / p>
< / script>
< script type =text / x-handlebarsdata-template-name =guide>
< p>此演示指南。< / p>
< / script>
< script type =text / x-handlebarsdata-template-name =animals>
< p>动物。您已选择:< / p>
< div class ='outlet'> {{outlet}}< / div>
< / script>
< script type =text / x-handlebarsdata-template-name =animals / index>
<! - 你不会看到这个,除非你禁用App.AnimalsIndexRoute重定向。 - >
< p>未选择动物。< / p>
< / script>
< script type =text / x-handlebarsdata-template-name =animals / cats>
< p> Cat。我可以喵像所有动物一样,I
< span class ='outlet'> {{outlet}}< / span>
< / p>
< / script>
< script type =text / x-handlebarsdata-template-name =animals / dogs>
< p>狗。我可以吠叫像所有动物一样,I
< span class ='outlet'> {{outlet}}< / span>
< / p>
< / script>
< script type =text / x-handlebarsdata-template-name =animal_mixin>
< p> am alive。< / p>
< / script>
< script type =text / x-handlebarsdata-template-name =application>
< div class =container>
< p>
选择我的插座的内容:
{{linklink}} /(root){{/ linkTo}}
{{#linkToabout}} / about { / linkTo}}
{{#linkToguide}} / guide {{/ linkTo}}
{{#linkToanimals}} / animals {{/ linkTo}}
{{#linkToanimals.cats}} / animals / cats {{/ linkTo}}
{{#linkToanimals.dogs}} / animals / dogs {{/ linkTo}}
< / p为H.
< 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:此控件对象没有connectOutlet方法
//
// controller.connectOutlet('animal_mixin');
}
});
App.initialize();
< / script>
< / html>
基本上animal_mixin是一个样板的一大块,我想反复用作mixin,将其放在任何地方想通过在那里放置一个插座并将其连接到此模板。我意识到这个例子是被设计的,因为我可以通过嵌套结构提供的继承来实现:animal_mixin的内容可以直接在动物模板中,我不需要在动物/猫中提及它动物/狗。如果我想要所有的动物,那就好了,但是让我们说我有另一个/我不想包含这个片段的动物的子路线。再次,这个例子是有创意的,但我希望这个问题和意图是清楚的。
你可以使用多个命名渠道。这是一个jsfiddle示例:。
< script type =text / x-handlebarsdata-template-name =application>
{{outlet header}}
{{outlet body}}
{{outlet navBar}}
< / script>
另请参阅的其他一些技巧。
事件:{
showModal:function(){
this.render('modal',{
into:'index',
outlet:'modalOutlet ',
控制器:this.controllerFor('modal')
});
}
}
I'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'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 withUncaught TypeError: Object <(generated animals.cats controller):ember170> has no method 'connectOutlet'
. - announcement of Ember.js Router API v2. Specifically the bottom couple comments (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 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'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 accomplish:
- 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 ownsetupController
method) and callcontroller.connectOutlet
here. This fails as described above; the controller object passed into this method does not have aconnectOutlet
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.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">
<!-- 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
// (uncomment 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.
You can use multiple named outlets. Here's a jsfiddle example: http://jsfiddle.net/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')
});
}
}
这篇关于Ember.js v2路由器中有多个插座的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!