我想在左边创建一个页面,我有固定的视图(一些过滤器),它们应用于右边的结果。
例如左边是根据流派,标题,创作年份过滤电影的过滤器.... 右侧是不同的图表和表格,它们根据所选的过滤器进行更新。
所以我想在左边有一个固定的视图,然后在右边有一个根据路线改变的出口。
这是正确的方法吗?如果是,我无法弄清楚如何将过滤器更改传达给右侧的控制器。
这个JSFiddle显示了类似的设置:http://jsfiddle.net/DEHcK/2/
在ContentRoute中 - > setupController我得到一个NavigationController的实例,但后来我无法弄清楚如何更改someValue。
在上面的示例中,ContentController如何在NavigationController中获取someValue的更改?
这是实现我在ember中描述的应用程序的正确方法吗?
JavaScript的:
window.App = Ember.Application.create();
App.Router.map(function () {
this.route('content');
});
App.ContentRoute = Ember.Route.extend({
setupController: function (controller) {
controller.set('navigationController', this.controllerFor('navigation'));
}
});
App.ContentController = Ember.ObjectController.extend({
navigationController: null,
observerOfSomeValue: function () {
this.set('observedValue', this.get('navigationController.someValue'));
}.observes('navigationController', 'navigationController.someValue'),
observedValue: null
});
App.IndexRoute = Ember.Route.extend({
redirect: function () {
this.transitionTo('content');
}
});
App.NavigationView = Ember.View.extend({
init: function () {
this._super();
this.set('controller', this.get('parentView.controller').controllerFor('Navigation'));
},
templateName: "navigation"
});
App.NavigationController = Ember.ObjectController.extend({
someValue: 'xx',
observedValue: null,
observerOfSomeValue: function () {
this.set('observedValue', this.someValue);
}.observes('someValue')
});
HTML:
<script type="text/x-handlebars" data-template-name="application" >
<div>
{{view App.NavigationView}}
</div>
<div>
{{ outlet }}
</div>
</script>
<script type="text/x-handlebars" data-template-name="navigation" >
Change {{view Ember.TextField valueBinding="controller.someValue"}}
<div>observed value in same view: {{controller.observedValue}}</div>
</script>
<script type="text/x-handlebars" data-template-name="content" >
<div style="margin-top: 2em">
observed value in another view: {{observedValue}}
</div>
</script>
答案 0 :(得分:25)
我已经完成了created you a JSFiddle并基本实现了你所追求的目标。我认为值得尽一切努力让你抓住Ember。
<强>路由器强>
我们现在正在配置IndexRoute
,我们会为{{outlet}}
存储所有歌曲。
App.IndexRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('content', [
Ember.Object.create({ title: 'Stairway to Heaven', genre: 'Metal' }),
Ember.Object.create({ title: 'Ratts of the Capital', genre: 'Post Rock' }),
Ember.Object.create({ title: 'Wonderwall', genre: 'Brit Pop' }),
Ember.Object.create({ title: 'Last Flowers', genre: 'Indie Rock' })
]);
}
});
很有可能这个代码将被替换为您的后端Ruby / PHP的某种AJAX调用。但就目前而言,我们将赋予IndexRoute
设置控制器的责任(因此setupController
)。这个责任也可以在控制器本身上进行,并且抽象出AJAX调用可能是一个好主意,因为你将有许多类似的AJAX调用。
您也可以决定use Ember's DataStore,这将再次改变控制器的实现。
索引控制器
接下来我们要设置我们的IndexController
(我们真的是SongsController
),我们希望这个控制器有两个职责:
为此我们创建了一个computed property来过滤掉内容,因为我们不想直接操作特殊的content
数组。
App.IndexController = Ember.ArrayController.extend({
content: [],
excludeGenres: [],
filteredContent: function() {
var excludeTheseGenres = this.get('excludeGenres').mapProperty('genre');
return this.get('content').filter(function(model) {
return Boolean(jQuery.inArray(model.get('genre'), excludeTheseGenres) === -1);
});
}.property('excludeGenres.length', 'content.length')
});
excludeGenres
将采用一系列流派对象。例如,如果“Post Rock”包含在excludeGenres
中,那么我们将不会显示任何“Post Rock”相关歌曲,但如果它不存在,那么我们将向他们展示! IndexController
没有维护此数组的责任,但它有责任在更新时更新其内容。
流派控制器
也许是我们这个小应用程序中最令人困惑的控制器,因为它实际上没有自己的任何内容,而是取决于IndexController
的内容。
App.GenresController = Ember.ObjectController.extend({
needs: ['index'],
genres: function() {
return this.get('controllers.index').mapProperty('genre').uniq();
}.property('controllers.index.length'),
toggle: function(genreName) {
var indexController = this.get('controllers.index'),
genres = indexController.get('excludeGenres'),
genre = indexController.findProperty('genre', genreName);
if (genres.findProperty('genre', genreName)) {
genres.removeObject(genre);
return;
}
genres.pushObject(genre);
}
});
流派控制器的职责可以这样定义:
content
的{{1}}数组,并在其长度发生变化时获取唯一的流派名称; IndexController
数组。要调用excludeGenres
方法,我们需要在我们的流派视图中指定一个操作,以便在单击时调用它:toggle
。现在,只要用户点击某个流派,就会调用<a {{action "toggle" genre}}>{{genre}}</a>
方法,并将该流派名称作为第一个参数传递。
一旦我们使用toggle
方法,就会确定该类型是否已被排除。如果它被排除,那么它将被删除,反之亦然。一旦我们添加/删除了类型,将再次触发toggle
计算属性,并且索引视图将无缝更新。
filteredContent
实际上没有自己的内容的原因是,当两个GenresController
数组存在关系时,管理两个content
数组似乎很愚蠢。由于类型可以从应用程序中存在的歌曲中确定,因此控制器可以从该列表中收集信息,并且只需提取它所需的信息 - 在我们的例子中,类型。
这样,如果添加/删除了一首歌曲,那么该流派列表可以保持同步。
<强>结论强>
我认为原始问题的答案是,为了让控制器彼此进行通信,您需要指定需要的内容(使用needs
)
答案 1 :(得分:1)
needs
已被弃用,并已在Ember 2.0中删除 - 请查看其Working Fiddle。
要在此复制/粘贴指南,而不是写:
Ember.Controller.extend({
needs: ['comments'],
newComments: Ember.computed.alias('controllers.comments.newest')
});
你应该写:
Ember.Controller.extend({
comments: Ember.inject.controller(),
newComments: Ember.computed.alias('comments.newest')
});
Ember.inject.controller()
将懒洋洋地查找控制器,其名称与其分配给的键相同 - 在本例中为comments
控制器。有关更多信息,请参阅Deprecation Guide。