trying to use params on main route (/) of my meteor app - meteor

I'm trying to use params on my main route. But in fact the params are not set and they are used in the path :
Router.map(function funcClientRouterMap(){
this.route('home', {
path: '/:_redirect?',
action: function funcClientRouterMapAction(){
console.log(this.path, this.params);
}
})
});
now if i try manual redirection here is what i get :
Router.go('home'); // it redirects on / => ok
Router.go('home', {_redirect: test}); // this.path = /test, and this.params is empty
How can i use _redirect like a params and not a route ?
Thanks

Router.go accepts a path as its first argument (per the docs). So if you were trying to programmatically cause the same result as the user going to /redirectMeSomewhere, you just use:
Router.go('/redirectMeSomewhere');
And this.params._redirect should be 'redirectMeSomewhere'.
Note that like #apendua implies, if you have other routes it could cause chaos to have a route defined as /:anything, because the other routes may never get triggered. If the above doesn't do the trick, try commenting out all your other routes to see if that changes anything.

Related

How to redirect from `/` to `/foo/<id>` using FlowRouter and MeteorJS?

In my scenario, I want everyone that visits our root URL to be auto-redirected to a url containing a document for collaboration and instant gratification.
Here, the router.coffee code is:
FlowRouter.route '/',
action: ->
console.log "I'm home!"
FlowRouter.go 'myProject'
name: 'myHome'
FlowRouter.route '/my/:projectId',
subscriptions: (params) ->
#register 'currentProject', Meteor.subscribe 'project', params.projectId
action: ->
BlazeLayout.render 'myBody'
name: 'myProject'
I want the root URL to redirect to /my/:projectId but I'm unsure of how to retrieve the auto-generated projectId and redirect using with either FlowRouter.go or FlowRouter.redirect.
Is this possible?
If yes, how?
Thanks for your help!
Since the data may not be available when the route action execute,
the best is to re-route at the template level.
It might be a good idea to use the Template.[name].onCreated() function
and put inside it something like the following code:
pID = ... // Get the user project ID from wherever you saved it
var params = {projectId: pID};
// Set the project URL including the :projectId parameter and re-route the user
FlowRouter.go("myProject", params);

Iron Router: How to Provide Same Data to Multiple Routes

It's evident how to provide route-specific data, i.e. through the use of a controller:
PostController = RouteController.extend({
layoutTemplate: 'PostLayout',
template: 'Post',
waitOn: function () { return Meteor.subscribe('post', this.params._id); },
data: function () { return Posts.findOne({_id: this.params._id}) },
action: function () {
this.render();
}
});
But how does one provide data for the application in general? In the case that every route needs to be subscribed to the same subset of information, so that the pub/sub doesn't need to be re-done on every route change. Thanks!
It sounds to me like you are looking for a completely general publication/subscription scheme so that you do not have to define the waitOn/data option combination for every single route or route controller that you define. In that case, you can simply publish a given set of data on the server like so:
Meteor.publish('someData', function() {
return SomeDataCollection.find({});
});
and subscribe to that set of data on the client like so:
Meteor.subscribe('someData');
With this publication/subscription pair setup, you will have access to the data provided in all routes. You just have to make sure that you check for non-existent data in your code to handle the first load of any given template when the data has not been loaded on the client yet. In this manner, you would never have to actually define a the waitOn and data options for any route or route controller.
If you would like to utilize Iron Router in a different way than through route controllers, you also have the option of waiting on one/many subscriptions globally by using the Router.configure({}); function. To use the example above:
Router.configure({
waitOn: function() {
return Meteor.subscribe('someData');
}
});
For information about this route option and all of the other options that you have available at a global level, check this out.

Implementing a simple search with Meteor and Iron Router

In the next phase of my Meteor journey (read: learning the ropes!), I'd like to implement a simple search based on user inputed values, then redirect to a route specific to the record returned from the server.
At the moment, I'm picking up the inputed values via this code:
Template.home.events 'submit form': (event, template) ->
event.preventDefault()
console.log 'form submitted!'
countryFirst = event.target.firstCountrySearch.value
countrySecond = event.target.secondCountrySearch.value
Session.set 'countryPairSearchInputs', [countryFirst, countrySecond]
countryPairSearchInputs = Session.get 'countryPairSearchInputs'
console.log(countryPairSearchInputs)
return Router.go('explore')
Happily, the console log returns the desired countryPairSearchInputs variable - an array of two ids. In my routes.coffee file I then have the following:
#route "explore",
path: "/explore/:_id"
waitOn: ->
Meteor.subscribe 'countryPairsSearch'
On the server side, I have:
Meteor.publish 'countryPairsSearch', getCountryPairsSearch
And finally, I have a search.coffee file in my /lib directory that defines the getCountryPairsSearch function:
#getCountryPairsSearch = ->
CountryPairs.findOne $and: [
{ country_a_id: $in: Session.get('countryPairSearchInputs') }
{ country_b_id: $in: Session.get('countryPairSearchInputs') }
]
With regards to the search function itself, I have a CountryPairs collection where each record has two ids (country_a_id and country_b_id) - the aim here is to allow users to input two countries, with the corresponding CountryPair then being returning.
I'm currently struggling to tie all the pieces together - the console output on searching is currently:
Uncaught Error: Missing required parameters on path "/explore/:_id". The missing params are: ["_id"]. The params object passed in was: undefined.
Any help would be greatly appreciated - as you can probably tell I'm new to Meteor and am still getting used to the pub/sub methodology!
Edited: mixed up client/server for the publish method when I first posted - the danger of late-night posting!
First, seems you're expecting an :id parameter on your 'explore' route.
If I understand you're case, you're not expecting any params here, so you can just delete ':id' from your route:
#route "explore",
path: "/explore/"
waitOn: ->
Meteor.subscribe 'countryPairsSearch'
or either add a params to your Router.go call:
Router.go('explore', {_id: yourIdVar});
Secondly, you're trying to use a client function: Session.get() server-side. Try to update the publication using a parameter ; or using a method.call.
client-side
Meteor.subscribe 'countryPairsSearch' countryA countryB
not sure about the coffeescript syntax, check http://docs.meteor.com/#/full/meteor_subscribe
and server-side
#getCountryPairsSearch = (countryA, countryB) ->
CountryPairs.findOne $and: [
{ country_a_id: $in: countryA }
{ country_b_id: $in: countryB }
]

Force iron-router to go to current route

I have created a route like:
this.route('design.create', {
path: '/design',
template: 'Design',
I have wroten some waitOn, data, onBeforeAction, onStop related and executed when the route is loaded.
I have a "strange" use case:
Where I'm already in the route design.create I would like re-init it (execute again waitOn, data, onBeforeAction, onStop).
A simple: Router.go('design.create') not works...I guess because I'm already on the same route.
Seems that:
Router.current()._computation.invalidate()
Do what I want...but it's not very elegant call a private method
Set a dependency by using a session variable in the onBeforeAction and change the session variable when you what the current route to get rerun:
...
onBeforeAction: function() {
Session.get('dependOnMe')
// the acutal onBeforeAction-code goes here
}
...
...
// somewhere else
Session.set('dependOnMe', new Date())
// will trigger the onBeforeAction again
...

How to handle / ignore a bad route with durandal?

I'm trying to conditionally block a route from being accessed. I think this can be done with guardRoute: http://durandaljs.com/documentation/Router/
function guardRoute(routeInfo, params, instance) : object - Before any route is activated, the guardRoute function is called. You can plug into this function to add custom logic to allow, deny or redirect based on the requested route. To allow, return true. To deny, return false. To redirect, return a string with the hash or url. You may also return a promise for any of these values.
I'm not sure how to specify which route should be accessed though, or how to re-route to another view if I need to deny access. Can someone post an example of its use in this manner?
You should use guardRoute before activating the router e.g. in shell.js.
The example is taken from a Durandal 2.0 alpha site. AFAIK guardRoute hasn't changed from 1.2, but setting a breakpoint will allow you to figure out what arguments are passed in for 1.2.
As a general rule, return true to allow navigation, false to prevent it and a hash or url value to redirect.
define(['plugins/router'], function (router) {
// Redirecting from / to first route in route.map
router.guardRoute = function(routeInfo, params, instance){
if (params.fragment === ''){
return routeInfo.router.routes[0].hash;
}
return true;
};
...
return {
...
router: router,
activate: function () {
router.map([
---
]);
return router.activate();
}
};
});
I am a newbie to durandaljs 2.0 having only used it for a couple of weeks so this was one of my first stumbling blocks. see my code below
router.guardRoute = function (routeInfo, params, instance) {
var insecureRoutes = ['login', 'terms','signup','password'];
if ($.inArray(params.fragment, insecureRoutes) || mymodule.isAuthenticated()) {
return true;
} else {
return 'login/' + params.fragment;
}
};
I also define a route for the login page like this
{ route: 'login/(:returnroute)', moduleId: 'viewmodels/login', nav: false },
This allows you to optionally specify a return rout so that after login you can redirect the user to where ever it is they were initially trying to go to. I hope it helps someone

Resources