我正在尝试实现一个控制器needing另一个(CampaignsNew
需要AppsIndex
),看起来像
App.CampaignsNewController = Ember.Controller.extend({
needs: ['appsIndex']
});
在我的CampaignsNew
模板中,我通过
{{#if controllers.appsIndex.content.isUpdating}}
{{view App.SpinnerView}}
{{else}}
{{#each controllers.appsIndex.content}}
{{name}}
{{/each}}
{{/if}}
然而controllers.appsIndex.content.isUpdating
永远不会成立。即它会在加载数据之前尝试显示数据。
我的AppsIndex
路线已覆盖模型:
App.AppsIndexRoute = Ember.Route.extend({
model: function(controller) {
var store = this.get('store').findAll('app');
}
...
});
如果我在CampaignsNew
路线中添加相同的代码并将模板修改为each
到controller.content
,我就可以使用它。哪位对我说needs
没有使用这条路线?如果我转到/apps
页面并加载数据,然后导航到/campaigns/new
页面,它也会有效。
我如何让它工作?谢谢!
修改 根据要求,我的路由器的相关部分:
App.Router.map(function() {
this.resource('apps', function() {
...
});
this.resource('campaigns', function() {
this.route('new');
});
});
AppsIndex
访问/apps
,CampaignsNew
访问/campaigns/new
EDIT2: 在实施了@ kingpin2k的建议之后,我发现Ember正在抛出一个错误。以下是更新的文件和收到的错误。
App.CampaignsNewController = Ember.ObjectController.extend({
pageTitle: 'New Campaign'
});
App.CampaignsNewRoute = Ember.Route.extend({
model: function(controller) {
return Ember.RSVP.hash({
campaign: this.store.createRecord('campaign'),
apps: this.store.find('app')
});
// return this.store.createRecord('campaign');
},
setupController: function(controller, model){
controller.set('apps', model.apps);
this._super(controller, model.campaign);
}
});
Ember引发了这个错误:
Error while loading route: Error: Assertion Failed: Cannot delegate set('apps', <DS.RecordArray:ember689>) to the 'content' property of object proxy <App.CampaignsNewController:ember756>: its 'content' is undefined.
我read online这是因为内容对象不存在。如果我这样设置:
App.CampaignsNewController = Ember.ObjectController.extend({
content: Ember.Object.create(),
...
});
然后页面加载没有错误,当检查Ember Chrome扩展程序时,我可以看到数据已加载。但它没有在页面上显示。我想这是因为content
对象存在,所以Ember没有等待模型的承诺在渲染模板之前完成。看起来很奇怪,你应该以这种方式定义内容。有关如何处理这个的任何见解?
编辑3:问题在another thread
中为我解答答案 0 :(得分:2)
根据您的路由器,apps
不是campaigns/new
的父级。
这意味着有人可以点击#/campaigns/new
,Ember会点击ApplicationRoute
,CampaignsRoute
和CampaignsNewRoute
来填充所请求网址的必要信息。使用需求作为控制器之间的通信方式实际上只在祖先模式中有意义(也就是与父母,祖父母等沟通)。
正如另一个快速记录,AppsIndex
是Apps
的路线,当您的网址包含儿童时,它不会被点击。 e.g。
this.resource('apps', function() {
this.resource('chocolate', function(){
.....
});
});
#/apps/chocolate
ApplicationRoute
AppsRoute
ChocolateRoute
ChocolateIndexRoute
仅当您未指定资源的路径时才会触发索引路由,并且您正在访问该确切的资源(也就是没有超过该资源的任何内容)。
您可以从特定的钩子返回多个模型:
App.FooRoute = Em.Route.extend({
model: function(){
return Em.RSVP.hash({
cows: this.store.find('cows'),
dogs: this.store.find('dogs')
});
}
});
如果您希望主模型仍为奶牛,可以在setupController
级别进行切换。
App.FooRoute = Em.Route.extend({
model: function(){
return Em.RSVP.hash({
cows: this.store.find('cows'),
dogs: this.store.find('dogs')
});
},
setupController: function(controller, model){
controller.set('dogs', model.dogs); // there is a property on the controller called dogs with the dogs
this._super(controller, model.cows); // the model backing the controller is cows
}
});
在这里查看第二个答案,EmberJS: How to load multiple models on the same route?(第一个也是正确的,只是没有提到从模型钩子返回多个模型的问题)。
您也可以在setupController
期间设置属性,但这意味着在页面加载时它将不可用,但稍后会异步。
如果您不打算使用型号支持控制器,请使用控制器。
App.FooRoute = Em.Route.extend({
model: function(){
return undefined;
}
});
如果要将控制器的模型设置为某个集合,则使用ObjectController。
App.FooRoute = Em.Route.extend({
model: function(){
return Em.RSVP.hash({
cows: this.store.find('cows'),
dogs: this.store.find('dogs')
});
}
});
如果某些东西将成为某种集合,请使用ArrayController。
App.FooRoute = Em.Route.extend({
model: function(){
return ['asdf','fdsasfd'];
}
});
如果覆盖setupController,它将不会设置控制器的模型,除非您明确告诉它,或使用this._super
。
App.FooRoute = Em.Route.extend({
model: function(){
return Em.RSVP.hash({
cows: this.store.find('cows'),
dogs: this.store.find('dogs')
});
},
setupController: function(controller, model){
controller.set('cows', model.cows);
controller.set('dogs', model.dogs);
// uh oh, model isn't set on the controller, it should just be Controller
// or you should define one of them as the model
// controller.set('model', model.cows); or
// this._super(controller, model.cows); this does the default setupController method
// in this particular case, ArrayController
}
});