Search code examples
meteoriron-router

Understanding how Router.go() works in Meteor


I'm just learning Meteor now from the great Discover Meteor book and I'm struggling to understand something about how Router.go() functions which I thought might be something that other beginners could use an answer to.

Context: The code below does what it's supposed to - it picks up the url and title values from the postSubmit form (code not included for the form) and uses that to create a new post. Then it uses Router.go() to take the user to the postPage template at a posts/:_id url, displaying the information for the newly created post. This code all works.

My question is: I would expect that when you call Router.go(), as well as passing in the 'postPage' template, what you would need to pass in as the second parameter is the post id element in the form {_id: post._id} (which also works, I've tried it) as that is what the route requires. So why am I passing in the post var (which includes the url and title) rather than the ID?

Here's my code:

//post_submit.js
Template.postSubmit.events({ 'submit form': function(e) {
    e.preventDefault();

    var post = {
    url: $(e.target).find('[name=url]').val(),
    title: $(e.target).find('[name=title]').val()
    };

    post._id = Posts.insert(post);
    //THE 'post' PARAMETER HERE INSTEAD OF '{_id: post._id}' IS WHAT I'M QUESTIONING
    Router.go('postPage', post);
    }
});

And the code for the router:

//Route for the postPage template
Router.route('/posts/:_id',
  {name: 'postPage',
  data: function(){ return Posts.findOne(this.params._id); }
});

Solution

  • Good question - I also found this confusing when I first saw it. Here's a sketch of what's going on:

    1. The router parses /posts/:_id and figures out that it should be passed a context object which contains an _id field.
    2. You call Router.go with a context object that contains an _id field.
    3. The router takes your context object and copies the value of _id into this.params.

    Because the router understands which fields are required (and ignores the rest), it doesn't actually matter if you pass in {_id: 'abc123'} or {_id: 'abc123', title: 'hello', author: 'bob'}. The fact that the latter works is simply a convenience so you don't have to extract the _id into a separate object.