【问题标题】:Ember JS - Having trouble loading multiple models into a route with belongsTo relationshipEmber JS - 无法将多个模型加载到具有 belongsTo 关系的路由中
【发布时间】:2015-08-20 20:28:27
【问题描述】:

我陷入了无法正确设置数据的情况。我希望能够加载我所有的帖子,并让每个帖子的作者数据也加载。这些是我的模型。

App.Post = DS.Model.extend({
    authorId:   DS.attr('number'),
    author:     DS.belongsTo('author'),
    title:      DS.attr('string'),
    body:       DS.attr('string'),
    snippet:    DS.attr('string'),
    postDate:   DS.attr('date'),
    imageName:  DS.attr('string'),

    postSnippit: Ember.computed();
    imageUrl: Ember.computed()})
});


App.Author = DS.Model.extend({
    name:        DS.attr('string'),
    imageName:   DS.attr('string'),
    posts:       DS.hasMany('post')
});

这是我路由器的相关部分......

App.Router.map(function() {
    this.route('blog', {path: '/blog'}, function() {
        this.resource('posts', { path: '/' });
        this.resource('post', {path: '/:id'});
    });
});

我已经为单个帖子正确设置了......

App.PostRoute = Ember.Route.extend({
    setupController: function(controller, model){
        this._super(controller, model);
        controller.set('post', model);
        controller.set('author', this.get('author'));
    },
    afterModel: function(){
        Ember.run.scheduleOnce('afterRender', this, scrollToNav);
        var self = this;
        var id = this.get('model.authorId');
        return this.store.find('author', id).then(function(result){
            self.set('author', result);
        });
    },
    model: function(params){
        return this.store.find('post', params.id);
    }
});

那么现在发生的事情是,我正在加载所有帖子的列表作为“博客”的模型。该路由左侧有一个侧边栏,其中包含所有博客文章的列表,右侧有一个默认加载“帖子”路由的出口。我需要两条路线的相同信息、所有帖子的列表以及作者信息。出口加载当前帖子并替换“帖子”模板,但保留左侧边栏中的帖子列表。目前我没有侧载 JSON 数据,因为我也无法弄清楚,所以现在数据是这样的......

{
    "posts": [
        {
            "id": "1",
            "authorId": "1",
            "title": "Title 1",
            "body": "This is the body 1",
            "uploadDate": "2015-06-03 19:26:15",
            "imageName": "image1.jpg"
        },
        {
            "id": "2",
            "authorId": "2",
            "title": "Title 2",
            "body": "This is the body 2",
            "uploadDate": "2015-06-03 19:26:15",
            "imageName": "image2.jpg"
        }
    ]
}

然后有一个单独的作者征集......

{
    "authors": [
        {
            "id": "1",
            "name": "John Smith",
            "email": "jsmith@gmail.com",
            "imageName": "image1.jpg",
            "gender": "M",
            "bio": "John Smith is an awesome dude who went to awesome school!",
            "facebookUrl": "null",
            "twitterUrl": null,
            "linkedinUrl": null
        }
    ]
}

现在这是我当前的路线对象(在来回穿过 100 万个事物之后)。

App.BlogRoute = Ember.Route.extend({
    model: function() {
        var store = this.store;
        var posts = store.findAll('post');
        return posts;

        /* *********************************
        **Tried this, keep getting an error saying 'content.slice' is not a function**
        *
        var authors = store.findAll('author');

         return Ember.RSVP.hash({
            posts: posts,
            authors: authors
        }).then(function(hash){
            return hash;
        }, function(reason){
            console.log(reason);
        });
        ********************************* */

    },
    setupController: function(controller, model) {
        this._super(controller, model);
        controller.set('model', model);
        controller.set('authors', this.get('authors')); //This doesnt do much, and I dont think its necessary.

        /* *********************************
        **Also tried this with the RSVP.hash function, would not render because of 'content.slice' error**

        controller.set('model', model.posts);
        controller.set('authors', model.authors)
        ********************************* */

    },
    afterModel: function(model) {
        Ember.run.scheduleOnce('afterRender', this, scrollToNav);
        var self = this;
        return this.store.findAll('author').then(function(result){
            self.set('authors', result);

        });
    }
});

App.PostsRoute = Ember.Route.extend({
    afterModel: function() {
        Ember.run.scheduleOnce('afterRender', this, scrollToNav);
    },
    model: function() {
        return this.modelFor('blog');
    }
});

当前发生的行为是,除了作者信息之外,所有内容都加载到模板中。它仅在访问实际帖子后加载(例如:'posts/1'),然后从那时起,如果我访问帖子或博客路线,作者姓名将保留在那里。

我不知道如何让信息一直显示。从我在 ember 检查器中可以看到,两者的数据正在加载中!我可能缺少一些简单的东西。如果你们有解决方案,请告诉我。

还有一个次要问题,我确信这与某种方式有关。无论我选择哪种方法将数据设置到控制器,(例如:controller.set('posts', posts) 我都无法通过调用给定名称从每个循环中的模板中引用该数据。(例如:{{ #每个帖子作为 |post|}} 应该是正确的格式}} 如果这不是正确的方法,或者甚至是预期的方法,请纠正我。

仅供参考,这里是博客、帖子和帖子模板的相关部分。

<script type="text/x-handlebars" id="blog">
    <div class="container-fluid">
        <h3>Posts</h3>
        <ul>
            {{#each model as |post|}}
            <li>
                {{#link-to 'post' post}}
                <h3>{{post.title}}</h3>
                <h4>{{post.author.name}}</h4>
                <h5>{{format-date post.date}}</h5>
                {{/link-to}}
            </li>
            {{else}}
                No Models Loaded!
            {{/each}}
        </ul>
    </div>
    <div class="container-fluid">
        {{outlet}}
    </div>
</script>

<script type="text/x-handlebars" id="posts">
    <h1>Recent Blog Posts</h1>
    {{#each model as |post|}}
    <h1>{{post.title}}</h1>
    <h4>By: {{post.author.name}} </h4>
    <h4>Posted: {{format-date post.date}} </h4>

    <img src={{post.imageUrl}} class="img-responsive img-thumbnail">

    <p class="indent">
        {{post.body}}
    </p>

    {{#link-to 'post' post}}Read More{{/link-to}}
    {{/each}}
</script>

<script type="text/x-handlebars" id="post">
    {{#link-to 'posts' class="pull-right"}}<span class="glyphicon glyphicon-chevron-left"></span>Back{{/link-to}}

    <h1>{{post.title}}</h1>
    <h4>Written By: {{author.name}} </h4>
    <h4>Posted: {{format-date post.date}} </h4>
    <hr/>
    <div class="img-container center">
        <img src={{post.imageUrl}} class="img-responsive img-thumbnail">
    </div>
    <br/>
    <p class="indent">
        {{post.body}}
    </p>
</script>

注意:我尝试了几个不同版本的 Ember,无论我使用哪个版本,我都会收到“content.slice 不是函数”错误,所以我确定我的某些东西我的做法是错误的,但这里有一些额外的信息以防万一:D!

VERSION INFO:

Ember Inspector:      1.8.1
Ember:                1.13.0-beta.2+76473dd3
Ember Data:           1.0.0-beta.18
jQuery:               2.1.4

【问题讨论】:

  • 这是什么postSnippit: Ember.computed(); imageUrl: Ember.computed()})
  • 您是否尝试过简化为仅发布帖子?
  • 哦,我刚刚删除了尸体,因为它们无关紧要。应该删除整个东西,但我不确定它们是否会影响任何东西
  • 好帖子和博客,都有同样的问题。据我所知,该模型正在从“博客”传递到“帖子”。在加载单个“帖子”之前没有任何作者信息。我已经测试了从“帖子”中删除所有内容并加载“博客”,但同样的事情发生了。我不认为嵌套是问题,我没有在正确的时间/以正确的方式加载作者。如果博客加载正确,我相信它们都应该:D

标签: javascript model-view-controller ember.js ember-data


【解决方案1】:

1) 我建议你不要使用store.findAll,因为这是私有的 api 方法。 api link。正确的方法是改用store.find('modelName')。例如,

model: function() {
  return this.store.find('post'); // promise to find all posts
}

2) 如果你想在一个路由中加载所有帖子和所有作者(例如在博客路由中)

App.BlogRoute = Ember.Route.extend({

  model: function() {
    return Ember.RSVP.hash({
      posts: this.store.find('post'),
      authors: this.store.find('author')
    });
  },

  setupController: function(controller, modelHash) {
    controller.setProperties(modelHash);
    // or directly 
    // controller.set('posts', modelHash.posts);
    // controller.set('authors', modelHash.authors);
    // even
    // this.controllerFor('posts').set('authors', modelHash.authors);
  }
}); 

3) 我会简化发布路线代码:

App.PostRoute = Ember.Route.extend({
  model: function(params){
    return this.store.find('post', params.id);
  },

  afterModel: function(model){
    var self = this;
    return model.get('author').then(function(author) {
        self.controllerFor('post').set('author', author);
    });
  }
  // setupController not needed here
});

4) 您可能需要更多步骤。 Jsbin 将有助于给出准确的答案。

UPD 08/jun/15:看起来 findAll 很快就会公开https://github.com/emberjs/data/pull/3234

【讨论】:

  • 感谢您的回复。我尝试了 Ember.RSVP.hash,但出现“content.splice 不是函数”错误。这可以与使用 findAll 相关联吗?无论如何find调用findAll,使用find而不是findAll是简单的约定吗?我坚决同意所有这些变化。虽然,你能详细说明 afterModel 功能吗?你为什么使用controllerFor?以及是什么允许它隐式加载作者。知道这一点将有助于我的帖子/博客路线。我需要能够为一系列帖子执行此操作。再次感谢您,我会尽快弄一个 JSBin。 :D
  • 关于findAll: ember-data 现在正在发生显着变化,私有 api 正在发生变化而没有广泛的公告,我相信不处理私有 api 的更安全的方法。 controllerFor 因为当前控制器没有作为参数传递给 afterModel(据我所知)。
  • OK 这样就可以摆脱设置控制器了。我想我最初试图这样做,但找不到合适的方法。
  • 隐式加载作者(??):model.get('author')是一个promise,所以在afterModel中加载了作者,然后.then(function(author) { self.controllerFor('post').set('author', author); })只是通过作者对象设置属性author
  • 是的,后来我意识到了。我的意思是获取作者ID,但我想这不是必需的。我试图在一系列模型的背景下理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
相关资源
最近更新 更多