7
votes

I'm trying to write a simple blog with Ember. I can't figure out how to nest comments resource inside the post resource. (I used ember-cli to generate the app)

/app/router.js

var Router = Ember.Router.extend({
  location: ENV.locationType
});

Router.map(function() {
    this.resource('posts', { path: '/' }, function() {
        this.resource('post', { path: 'posts/:post_id' }, function() {
            this.resource('comments');
        });
    });
});

export default Router;

/app/templates/posts.hbs

<div class="col-xs-3">
    <h2>Posts</h3>
    {{#each}}
        <h4>{{#link-to 'post' this}}{{title}}{{/link-to}}</h4>
    {{/each}}
</div>
<div class="col-xs-9">
    {{outlet}}
</div>

/app/templates/post.hbs

<h2>
    {{#if isEditing}}
        {{input value=title}}
    {{else}}
        {{title}}
    {{/if}}
</h2>
<p>
    {{#if isEditing}}
        {{textarea value=body}}
    {{else}}
        {{body}}
    {{/if}}
</p>
<p>
    {{publishDate}}
</p>

{{#if isEditing}}
    <button {{action 'doneEditing'}}>Save</button>
{{else}}
    <button {{action 'edit'}}>Edit</button>
{{/if}}

{{!-- Should be outlet to Comments? --}}
{{outlet}}

/app/templates/comments.hbs

<h1>Comments</h1>

/app/model/post.js

var Post = DS.Model.extend({
    title: DS.attr('string'),
    body: DS.attr('string'),
    magic: DS.attr('string'),
    publishDate: DS.attr('date'),
    comments: DS.hasMany('comment')
});

Post.reopenClass({
    FIXTURES: [
        {
            id: 1,
            title: "Writing a blog in Ember",
            body: "I am writting a blog",
            magic: "heloo212",
            publishDate: "05/22/2104",
            comments: [1, 2]
        },
        {
            id: 2,
            title: "I'm shouting Ember",
            body: "I am shouting about Ember",
            publishDate: "05/22/2104",
            comments: 3
        }
    ]
});

export default Post;

/app/models/comment.js

var Comment = DS.Model.extend({
    body: DS.attr('string'),
    author: DS.attr('string'),
    createdAt: DS.attr('date'),
    post: DS.belongsTo('post')
})

Comment.reopenClass({
    FIXTURES: [
        {
            id: 1,
            body: "Woohoo",
            author: "Matthew",
            createdAt: "01/01/2015",
            post: 1
        },
        {
            id: 2,
            body: "Great Stuff",
            author: "Mark",
            createdAt: "01/02/2015",
            post: 1
        },
        {
            id: 3,
            body: "A comment",
            author: "Luke",
            createdAt: "01/04/2015",
            post: 2
        }
    ]
});

export default Comment;

app/routes/comments.js

var CommentsRoute = Ember.Route.extend({
    model: function() {
        return this.store.find('comment');
    }
});

export default CommentsRoute;

I expected to see my comments.hbs template appearing at the bottom of the post.hbs (currently just trying to put out Comments but I don't see anything and ember inspector is telling me:

Could not find "post.index" template or view. Nothing will be rendered Object {fullName: "template:post.index"}

1
will you show the posts and comments template also. And does the posts template work?Kingpin2k
Added both of those templates. The posts template works and renders the selected post as expected.brownie3003
I don't see any link to the comments section, and when you say ember inspector says that, are you referring to in the console, or what are you doing in ember inspector that's saying that?Kingpin2k
Maybe I've misunderstood it. I thought nesting comments inside post resource would mean that the {{outlet}} in post.hbs would display the comments? The console debug is showing that message not inspector, my bad.brownie3003

1 Answers

6
votes

Nested routes/resources aren't automatically rendered. Think of this example

Router.map(function() {
    this.resource('posts', { path: '/' }, function() {
        this.resource('post', { path: 'posts/:post_id' }, function() {
            this.resource('comments');
            this.resource('somethings');
        });
    });
});

There are multiple resources/routes under the post, either or could be rendered into the outlet.

For your particular case, there are a couple of things we'll need to fix.

First you'll need to mark comments as async, due to your json returning ids.

App.Post = DS.Model.extend({
    title: DS.attr('string'),
    body: DS.attr('string'),
    magic: DS.attr('string'),
    publishDate: DS.attr('date'),
    comments: DS.hasMany('comment', {async:true})
});

Second we'll want to set up routes for each resource/route that needs a model

App.PostsRoute = Em.Route.extend({
  model: function() {
        return this.store.find('post');
    }
});

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

App.CommentsRoute = Ember.Route.extend({
    model: function() {
        return  this.modelFor('post').get('comments');
    }
});

And then instead of linking to a single post, we link to comments. And ember will apply the passed in model to the route that has a dynamic model (IE :post_id).

{{#each}}
    <h4>{{#link-to 'comments' this}}{{title}}{{/link-to}}</h4>
{{/each}}

http://emberjs.jsbin.com/wekoxapi/1/edit