创建动态路由时出现Ember错误

时间:2014-11-23 03:54:35

标签: javascript ember.js

道歉,如果已经提出这个问题,我无法理解。

我正在尝试将Ember动态路由与模板链接。它不起作用。以下代码的错误为Error while processing route: favorite undefined is not a function

这个想法是主页面应该显示通过Ajax返回的收藏夹列表。每个最爱都应该有一个链接。用户单击链接,并将收藏夹注入同一页面上的相关模板。

主页面正常运行。使用下面的代码,链接目前显示index.html/#/12345ab,其中12345ab是product_id

HTML模板:

<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);
    }
});

3 个答案:

答案 0 :(得分:2)

从外观上看,您希望从父路线中找到模型。你可以这样做:

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

P.S。请注意params.product_id,它以字符串形式出现。您需要将其强制转换为所需类型,以便findBy正常工作。

P.S.S。我还应该补充一下,Ember。$。ajax返回一个承诺,但你希望模型是data.favorites,这是外部承诺的需要。如果您刚刚返回Ember。$。ajax并通过model.favorites访问了所有内容,您将不需要它。

答案 1 :(得分:0)

您的路由需要nested才能让子资源通过#modelFor访问父级。但是,如果您的UI未嵌套,则您的路径可能不应该是,因为嵌套路由也会连接相应的视图层次结构。

您可以随时根据ajax调用返回的数据子集定义favorite路由的模型:

//routes/favorite.js
model: function() {
    return Ember.$.getJSON('/favorites').then(function(favorites) {
      return favorites.findBy('id', params.product_id');
    });
}

但是,顶级.getJSON('/favoritescall 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资源共享。

答案 2 :(得分:0)

在Ember IRC频道的帮助下,这是工作代码。实质上,它为要呈现的favoritesfavorite模板创建索引模板。然后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>

<强> Router.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);
  }
});