DISABLE ADBLOCK

ADBlock is blocking some content on the site

ADBlock errore

Ember.js - Getting routes and models working together

StackOverflow https://stackoverflow.com/questions/18165236
 Checked

Question

i'm learning Ember.js but i'm struggling to figure out why my routes aren't working properly.

Here are the relevant parts of my app.js:

// Routes
App.Router.map(function() {

   this.resource('posts', { path: '/posts' });
   this.resource('post', { path: '/post/:id' });

});

// Handle route for posts list
App.PostsRoute = Ember.Route.extend({

    model: function() {
        return App.Post.findAll();
    }

});

// Handle route for single post
App.PostRoute = Ember.Route.extend({

    model: function(params){

        return App.Post.findById(params.id);
    }

});

// Post model
App.Post = Ember.Object.extend();

App.Post.reopenClass({
    findAll: function(){

        var posts = [];

        $.getJSON("/api/posts").then(function(response){

            response.posts.forEach(function(post){

                posts.pushObject(App.Post.create(post));

            });

        });

        return posts;
    },
    findById: function(id){

        $.getJSON("/api/post/" + id).then(function(response){

            return App.Post.create(response.post);

        });

    }
});

Then in my template I have this:

<!-- Post list -->
<script type="text/x-handlebars" data-template-name="posts">
    <div class="large-12 columns">
        <h1>Posts</h1>
        <hr>
        <ul>
            {{#each post in model}}
                <li>{{#linkTo 'post' post}}{{post.title}}{{/linkTo}}</li>
            {{/each}}
        </ul>
    </div>
</script>

<!-- Single post -->
<script type="text/x-handlebars" data-template-name="post">
    <div class="large-12 columns">
        <h1>{{title}}</h1>
        <div class="content">
            {{post_content}}
        </div>
    </div>
</script>

I'm having a few issues here. Firstly, the href attribute on the links in the post list are coming out like this:

#/post/<App.Post:ember217>

I can fix this by changing my post route to:

this.resource('post', { path: '/post/:post_id' });

But then when I try to navigate directly to a post by using a URL like /#/post/1 I get an error: Assertion failed: Cannot call get with 'id' on an undefined object.

Finally, if I leave my post route how it is (/post/:id) then visit the URL /#/post/1 none of the post data is displayed. I can see the correct API endpoint is called and no errors are shown in the console.

However, if i click through to the single post from the posts list the post is displayed properly but it uses the weird URL that I mentioned earlier - #/post/<App.Post:ember217>.

If this helps, this is the JSON the post models are created from:

{"post":
   {
      "id":2,
      "title":"Second post",
      "alias":"second-post",
      "postedOn":"2013-08-12 09:11:37",
      "authorId":1,
      "post_content":"Post content"
   }
 }

Sorry i know there's quite a bit there - I hope it's enough to give a clear picture of what I'm doing wrong.

Thank you

Solution

You are receiving this url #/post/<App.Post:ember217> because your dynamic segment is /post/:id, you have to change to yourmodel_id, in your case is /post/:post_id. Using this, by default the route serialize method will know that you want the id atribute of the post, in the url: /post/1, /post/2 etc. And no override will be needed in that case.

You have said that changing to post_id make the url generation works, but the navigation no, when navigate to url directly, but the problem isn't the routing, I think that is because you are using:

App.Post.findById(params.id);

You have to update to:

App.Post.findById(params.post_id);

Other problem that I see (don't know if is a typo mistake), you forget the return in ajax call:

findById: function(id){
  // you must return the ajax  
  return $.getJSON("/api/post/" + id).then(function(response){

    return App.Post.create(response.post);

  });

}

I hope it helps.

OTHER TIPS

Ember likes your objects to have an id property for generating the url. If you are going to use something other than id in the route (such as :post_id) you'll need tell Ember how to deserialize your model for generating the url.

 App.PostRoute = Ember.Route.extend({

   model: function(params){

      return App.Post.findById(params.id);
   },
   serialize: function(model) {
      return { id: model.get('id') };
   }

 });



 App.PostRoute = Ember.Route.extend({

   model: function(params){

      return App.Post.findById(params.id);
   },
   serialize: function(model) {
      return { post_id: model.get('post_id') };
   }

 });

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow