meteor iron router dynamic segment not working

2k views Asked by At

I've been looking into meteor and it's awesome! I've been looking for routing solutions and I found 'iron-router' which is cool, I managed to get the get static pages working with templates but when I go to /posts/123, the page does not render. I have been following a video on this site

https://www.eventedmind.com/feed/q8QWX5e7PTu8BEReY

Here's my code

blog.js EDITED

Posts = new Meteor.Collection('posts');

Router.configure({
  layout: 'layout',
  loadingTemplate: 'loading',
  notFoundtemplate: 'notFound'
});

Router.map( function (){
  this.route('posts', {
    path: '/',
    waitOn: function () {
      return App.subs.posts;
    },
    data: {
      posts: function () {
        return Posts.find({}, {sort: {order: 1}});
      }
    }
  });

  this.route('postShow', {
    path: '/posts/:_id'
  });
});

if (Meteor.isServer) {
  Meteor.publish('posts', function () {
    return Posts.find({}, {sort: {order: 1}});
  });

  Meteor.publish('post', function (id) {
    return Posts.find({_id: id});
  });
}

if (Meteor.isClient) {
  App = {
    subs: {
      posts: Meteor.subscribe('posts')
    }
  };

  PostShowController = RouteController.extend({
    template: 'postShow',
    before: function () {
      var _id = this.params._id;

      if(App.subs.post)
        App.subs.post.stop();

      App.subs.post = Meteor.subscribe('post', _id);
    },
    data: {
      body: function () {
        return Posts.findOne({_id: this.params._id});
      }
    },
    run: function () {
      this.render('postShow');
    }
  });
}

blog.html

<head>
    <title>IronRouter</title>
</head>

<body>
</body>

<template name="layout">
    <div class="container">
        <aside class="sidebar">
            <div class="sidebar-inner">
                {{yield 'sidebar'}}
            </div>
        </aside>

        <section class="content">
            <div class="content-inner">
                {{yield}}
            </div>
        </section>
    </div>
</template>

<template name="notFound">
  <h1>Not Found</h1>
</template>

<template name="loading">
  <h1>Loading...</h1>
</template>

<template name="posts">
  <h1>Posts</h1>
  <ul>
    {{#each posts}}
    <li>{{> postListItem}}</li>
    {{/each}}
  </ul>
</template>

<template name="postListItem">
    <a href="{{pathFor 'postShow'}}">
        {{title}}
    </a>
</template>

<template name="postShow">
  <p>
    {{body}}
  </p>
</template>

<template name="postShowSidebar">
  <h1>{{title}}</h1>
</template>
3

There are 3 answers

2
cmather On BEST ANSWER

I'm the author of the video and it may be a little out of date. My apologies. I would do the following:

  1. Change layout: 'layout' to layoutTemplate: 'layout'
  2. Remove the run method from your controller. That method actually does a lot and so if you want to override rendering you can use the action method instead. But in your case, you don't need to do any of that because it will happen automatically.
  3. This is sort of unrelated, but you don't need to stop the subscription yourself. It turns out, Meteor and iron-router will do this automatically when the computation is stopped (i.e. when you navigate to a new route).

I hope this helps!

2
Jeremy S. On

Try adding your PostShowController to the corresponding route:

this.route('postShow', {
  path: '/posts/:_id',
  controller: 'PostShowController'
});
3
Christian Fritz On

Maybe I'm missing something, but in your controller you say

data: function () {
  return Posts.findOne({_id: this.params._id});
},

but in your template you are using {{body}}, which I don't see being assigned anything anywhere. Doesn't that need to be as:

data: {
  body: function () {
    return Posts.findOne({_id: this.params._id});
  }
}