-
Notifications
You must be signed in to change notification settings - Fork 76
Meteor.Router API
This is a document explaining a potential API for routing in meteor. This may end up making it's way into core or simply remain separate in this smart package.
The idea is to re-write the package without a reliance on backbone, and to set it up in a way that makes more sense in the meteor world and is more in the spirit of other meteor APIs.
To find the current page:
Meteor.Router.currentPage();
Note that as in the current version of the package, this variable will usually be accessed via the currentPage
helper to render a specific variable, as in:
<!-- this will render the 'news' template in the current example -->
{{{render currentPage}}}
To define a route:
Meteor.Router.add({
'news': function () {
return 'news';
}
});
When the user browses to /news
, the currentPage
will be set to whatever this function returns. Note that the function will be called reactively -- i.e. if it checks any reactive dependencies and they change, then it will be re-run and the currentPage
variable may change. (Return something falsy to not change the currentPage
variable).
To navigate to a page:
Meteor.Router.to('news');
Changes the URL to http://your.host/news
and triggers any relevant functions (as if the user had browsed there directly).
The path may contain :variables
which will be provided to the routing function; additionally, this and more is available in the the this
object:
Meteor.Router.add({
'posts/:id': function(id) {
console.log('we are at ' + this.path);
console.log("we've matched: " + this.matches);
console.log("our parameters: " + this.parameters);
Session.set('currentPostId', id);
return 'showPost';
}
});
The current system of filtering in this package is the equivalent of an after_filter
in rails. A potential API:
Meteor.Router.addFilter({
'checkLoggedIn': function(page) {
if (Meteor.user()) {
if (Meteor.user().loading) {
return 'loading';
} else {
return page;
}
} else {
return 'signin';
}
});
})
And to use it, simply provide a set of names to apply it to via only
, or not to apply it to with except
:
Meteor.Router.filter({
'checkLoggedIn': {only: ['dashboard', 'newPost', 'newComment']}
});
Before filters are more tricky because it's unclear how to apply them. I don't want to think about this too hard until I know whether this is the sort of thing the router should be doing (I feel like it probably has to though because choosing to show loading
or 404
is definitely a routing issue).
Meteor.Router.addFilter({
'waitForData': function(id, collection, routingFn) {
var object = collection.findOne(id);
if (object) {
return routingFn(object);
// this is a method a collection that doesn't currently exist, but maybe should
} else if (collection.loading()) {
return 'loading';
} else {
return '404';
}
}
});
To make it simple to get the URL that corresponds to an object:
Meteor.Router.map({
"post": function(post) {
return "posts/" + post._id;
}
});
And to use it
// returns 'posts/7' for instance
Meteor.Router.for("posts", post);
Or directly:
// takes us to 'posts/7' right now
Meteor.Router.to("posts", post);
Taking this idea even further, we could define
Meteor.Router.connect('posts', Posts, function(post) {
return {'showPost', post};
});
Which could potentially take care of setting up a map
from simple posts to posts/:id
, and a routing function which pulls the relevant post
from the Posts
collection (probably using something like the waitForData
filter above). Unsure about if this is a good idea.