抱歉,如果已经问过这个问题,我无法弄清楚。
我正在尝试将 Ember 动态路由与模板链接。它不起作用。以下代码的错误Error while processing route: favorite undefined is not a function
这个想法是主页应该显示通过Ajax返回的收藏夹列表。每个收藏夹都应该有一个链接。用户单击链接,收藏夹将注入到同一页面上的相关模板中。
主页工作正常。使用下面的代码,链接当前显示index.html/#/12345ab
其中 12345ab 是product_id
。
模板:
<script type="text/x-handlebars" id="favorites">
{{#each favorite in arrangedContent}}
<div class="productBox">
{{#link-to 'favorite' favorite.product_id}}
<img {{bind-attr src=favorite.product_image}} />
{{/link-to}}
</div>
{{/each}}
{{outlet}}
</script>
<script type="text/x-handlebars" id="favorite">
<h2>{{product_name}}</h2>
<img {{bind-attr src=product_image}} />
</script>
路由器代码:
App.Router.map(function() {
this.resource('favorites', { path: '/'});
this.resource('favorite', { path: ':product_id' });
});
App.FavoritesRoute = Ember.Route.extend({
model: function() {
return Ember.$.ajax({
//this returns correctly
}).then(function(data) {
return data.favorites;
});
}
});
App.FavoriteRoute = Ember.Route.extend({
model: function(params) {
return App.Favorites.findBy('product_id', params.product_id);
}
});
更新:
下面的答案给出了以下代码,但如果用户通过 URL 或直接刷新直接转到页面,则由于尚未解析favorites
模型,它将失败。确切错误为:Cannot read property 'findBy' of undefined
App.FavoriteRoute = Ember.Route.extend({
model: function(params) {
return this.modelFor('favorites').findBy('product_id', params.product_id);
}
});
更新 2:整个路由器代码:
App.Router.map(function() {
this.resource('favorites', { path: '/'});
this.resource('favorite', { path: ':product_id' });
});
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return new Promise(function(resolve, reject) {
Ember.$.ajax({
url: 'MY_URL',
dataType: 'jsonp',
jsonp: 'callback'
}).then(function(data) {
resolve(data.favorites);
});
});
},
setupController: function(controller, model) {
return this.controllerFor('favorites').set('model', model);
}
});
App.FavoriteRoute = Ember.Route.extend({
model: function(
return this.controllerFor('favorites').get('model').findBy('product_id', params.product_id);
}
});
从外观上看,您希望从父路由中查找模型。 你可以这样做:
App.FavoriteRoute = Ember.Route.extend({
model: function(params) {
this.modelFor('favorites').arrangedContent.findBy('product_id', params.product_id);
}
});
更新:
问题是您从父路由的承诺没有得到正确解决。 您正在返回一个承诺,但该承诺的结果没有得到解析,即(返回 data.favorites)没有解析承诺。
将其更新为:
App.FavoritesRoute = Ember.Route.extend({
model: function() {
return new Promise(function(resolve, reject) {
Ember.$.ajax('yourURL').then(
function(data){
resolve(data.favorites);
});
});
}
});
还要包含此答案的初始反馈。 我有一个工作的 JSBin 反对实际的端点以表明它有效:http://jsbin.com/boloya/3/edit
附言 注意params.product_id,它以字符串的形式出现。 您需要将其强制转换为所需的类型,以便 findBy 正常工作。
附言我还应该补充一点,Ember.$.ajax 返回一个承诺,但您希望模型是 data.favorites 这是对外部承诺的需求。 如果你只是返回了Ember.$.ajax并通过model.favorites访问了所有内容,那么你就不需要它了。
您的路由需要嵌套,子资源才能通过 #modelFor
访问父资源。但是,如果您的 UI 不是嵌套的,则您的路由可能不应该嵌套,因为嵌套路由还会连接相应的视图层次结构。
您始终可以根据 ajax 调用返回的数据子集来定义favorite
路由的模型:
//routes/favorite.js
model: function() {
return Ember.$.getJSON('/favorites').then(function(favorites) {
return favorites.findBy('id', params.product_id');
});
}
但随后,顶级.getJSON('/favorites
)call would be made multiple times, every time the user enters
/收藏夹, and every time he enters
/收藏夹/:ID'。
相反,您可以让应用程序在输入时设置一次FavoritesController
。这样,您可以共享数据,但favorite
不必是favorites
的子路由。它可能看起来像这样:
//routes/application.js
model: function() {
return Ember.$.getJSON('/favorites');
},
setupController: function(controller, model) {
this.controllerFor('favorites').set('model', model);
}
和
//routes/favorite.js
model: function(params) {
return this.controllerFor('favorites').find('id', params.id);
}
这样,JSON 仅加载一次,ApplicationRouter
为您连接FavoritesController
,并与favorite
资源共享数据。
在Ember IRC频道的帮助下,这是工作代码。实质上,它为要呈现的favorites
和favorite
模板创建一个索引模板。然后,favorite
路由可以访问其父路由favorites
,但仍呈现到同一模板区域中。
.HTML
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" id="favorites">
{{outlet}}
</script>
<script type="text/x-handlebars" id="favorites/index">
{{#each favorite in arrangedContent}}
<div class="productBox">
{{#link-to 'favorite' favorite.product_id}}
<img {{bind-attr src=favorite.product_image}} />
{{/link-to}}
</div>
{{/each}}
{{outlet}}
</script>
<script type="text/x-handlebars" id="favorite">
<h2>{{product_name}}</h2>
<img {{bind-attr src=product_image}} />
</script>
路由器.js
App.Router.map(function() {
this.resource('favorites', { path: '/'}, function () {
this.resource('favorite', { path: ':product_id' });
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function () {
this.replace('favorites');
}
});
App.FavoritesRoute = Ember.Route.extend({
model: function() {
return new Promise(function(resolve) {
Ember.$.ajax({
url: 'MY_URL',
dataType: 'jsonp',
jsonp: 'callback'
}).then(function(data) {
resolve(data.favorites);
});
});
}
});
App.FavoriteRoute = Ember.Route.extend({
model: function (params) {
return this.modelFor('favorites').findBy('product_id', params.product_id);
}
});