Meteor JS: Conditional subscriptions, based on passed arguments, in Iron Router? - javascript

This is really two questions:
Is it possible to conditionally subscribe to collections within Iron Router's waitOn option?
Is it possible to pass in objects as an argument in Router.go()?
I am trying to reduce the delay in rendering a view, when creating a new post within my app. I tried passing in an isNew property as an argument for Router.go(), but had no luck:
// Router call after creating a new post
Router.go('postPage', {
_id: id,
isNew: true,
post: newPostObject
});
// router.js
Router.map(function() {
this.route('postsList', {
path: '/'
});
this.route('postPage', {
path: '/:_id',
waitOn: function() {
//This returns only _id for some reason.
console.log(this.params);
if (this.params.isNew != true) {
return [
Meteor.subscribe('singlePost', this.params._id),
Meteor.subscribe('images', this.params._id),
]
}
},
data: function() {
if (this.params.isNew == true) {
return this.params.post
else {
return Posts.findOne(this.params._id);
}
}
});
});

After some digging, it looks likes Iron Router supports an options hash as a third argument in the Router.go() method:
Router.go( 'postPage', {_id: id}, {isNew: true} );
To access it in the route, you can use then use this.options. To get the value of isNew in the above example, use this.options.isNew.

you can only access Dynamic Path Segments by this.params. so to get this.params.isNew working you need to have it like this.
this.route('postPage', {
path: '/:_id/:isNew',
waitOn: function() {}
...
});

Related

How to fix FlowRouter.getParam from being 'undefined'

I am adding a new page to a website, and I am copying the code that already exists and is currently working in the website. Why is the FlowRouter.getParam coming up undefined when it works everywhere else?
client/JobInvoice.js
import { Invoices } from '../../../imports/api/Invoice/Invoice';
Template.InvoicePage.onCreated(function(){
const user = FlowRouter.getParam('_id');
console.log(user);
this.subscribe('invoices', user);
});
lib/router.js
Accounts.onLogout(function(){
FlowRouter.go('home');
});
FlowRouter.notFound = {
action: function() {
FlowRouter.go('/404');
}
};
const loggedIn = FlowRouter.group({
prefix: '/secure'
});
loggedIn.route( '/invoice', {
name: 'invoice',
action() {
BlazeLayout.render('FullWithHeader', {main:
'InvoicePage'});
}
});
What am I missing?
FlowRouter allows you to define routes with dynamic attributes (path-to-regexp), which are often representing document ids or other dynamic attributes.
For example
FlowRouter.route('/invoice/:docId', { ... })
would define a route that matches a pattern like /invoice/9a23bf3uiui3big and you usually use it to render templates for single documents.
Now if you want to access the document id as param docId inside the corresponding Template you would use FlowRouter.getParam('docId') and it would return for the above route 9a23bf3uiui3big.
Since your route definitions lacks a dynamic property, there is no param to be received by FlowRouter.getParam.
A possible fix would be
loggedIn.route( '/invoice/:_id', {
name: 'invoice',
action() {
BlazeLayout.render('FullWithHeader', {main:
'InvoicePage'});
}
});
to access it the same way you do for the other templates.
Readings
https://github.com/kadirahq/flow-router#flowroutergetparamparamname
Here is what I ended up doing and it works.
loggedIn.route( '/invoice/:id', {
name: 'invoice',
action() {
BlazeLayout.render('FullWithHeader', {main: 'InvoicePage'});
}
});

Meteor Iron Router doesn't call onBeforeAction if data returns null/undefined

I am using Meteor with iron-router and I'm trying to redirect the user back to the login-page if he is no logged in. But on some routes the onBeforeAction is not called. And as I discovered this has something to do with the data which is returned by the data function on the route.
If data returns null/undefined the onBeforeAction is not called and it displays the layout without the data.
If data returns i.e. an empty object it is calling the onBeforeAction and redirecting to the login-page.
1) Is this the right behaviour or is there something wrong with my route definition?
2) Is it possible that the onBeforeAction function is called before the page is rendered? Because it always show the layout/view for a short moment which is not that nice.
So, I have this route:
this.route('dashboardPortfolio', {
path: ['/dashboard/portfolio'],
layoutTemplate: 'dashboardLayout',
yieldTemplates: {
'header': {to: 'header'},
'dashboardHeader': {to: 'dashboardHeader'},
'footerMain' : {to: 'footer'}
},
notFoundTemplate: 'notFound',
loadingTemplate: 'dashboardLoading',
waitOn: function() {
return Meteor.subscribe("portfolio-edit");
},
data: function() {
var portfolio = Portfolio.findOne({user: Meteor.userId()});
if(portfolio) return portfolio;
else return {};
// return Portfolio.findOne({user: Meteor.userId()});
}
});
and my onBeforeAction:
var OnBeforeActions;
OnBeforeActions = {
loginRequired: function(route, asd, pause) {
if (!Meteor.userId()) {
this.layout('login');
this.render('login');
} else {
this.next();
}
}
};
Router.onBeforeAction(OnBeforeActions.loginRequired, {
except: ['register', 'login', 'about', 'portfolio']
});
Try replacing "except" by "only" in the next line:
except: ['register', 'login', 'about', 'portfolio']
Good luck!

Easiest way to get Json / Collection through Meteor Iron Router

I'm creating a set of routes, for example
/ - should render home page template
/items - should items page template
/items/weeARXpqqTFQRg275 - should return item from MongoDB with given _id
This is example of what I'm trying to achieve
Router.route('items/:_id', function () {
var item = return myItems.find(:_id);
this.render(item);
});
[update - solved]
solved this by using Router.map on server side instead of Router.route
Router.map(function () {
this.route('post', {
path: 'items/:_id',
where: 'server',
action: function(){
var id = this.params._id;
var json = myItems.findOne({_id: id});
this.response.setHeader('Content-Type', 'application/json');
this.response.end(JSON.stringify(json, null, 2));
}
});
});
There are several problems with your code.
First, it seems you want to get the _id parameter from the url and don't know how. It's stored on this.params, so it's this.params._id.
Second, the first parameter you should send to find is a MongoDB query that in your case would be { _id: this.params._id }.
Third, that's not how you render something in Iron Router. The string parameter on the render method is the name of the template you want to render, not the item.
Assuming that myItems is a valid collection and your template is called showItem, your code should be something like:
Router.route('items/:_id', {
name: 'showItem',
data: function () {
return myItems.find({ _id: this.params._id });
}
});
Try something like this:
Router.map(function () {
this.route('items/:myItemId', {
data: function(){
return myItems.findOne({_id: this.params.myItemId});
}
});
});
good luck!

Using this.transitionTo to change query params gives error

Using pretty much copy paste from Ember.js docs
App.CresShowResultController = Ember.ArrayController.extend({
queryParams: ['county'],
county: null,
actions: {
displayQueryData: function(){
this.transitionTo({queryParams: {county: 'someCounty'}});
},
},
});
The action is called from another controller after a form is analysed.
I get an error: Uncaught TypeError: undefined is not a function
Here is the route as well.
App.CresShowResultRoute = Ember.Route.extend({
renderTemplate: function(){
this.render('showResult');
}
});
SideQuestion: How can I use transitionTo to change URL parameters straight from another controller without using the action "displayUseryData" as middleman function?
EDIT: Added my Router.map to specify:
App.Router.map(function(){
this.resource('cres', function() {
this.route('showResult');
});
this.resource('about');
this.resource('posts', function() {
//child route posted inside the parent
this.resource('post', { path: ':post_id'});
});
});
Like always, thank you for any helping comments!
try:
App.CresShowResultController = Ember.ArrayController.extend({
queryParams: ['county'],
county: null,
actions: {
displayQueryData: function(){
this.transitionTo({queryParams: {county: 'someCounty'}});
}.bind(this),
},
});
I think that "this" in the displayQueryData function is a window reference.
In the case you reference above, just updating the queryParam itself will have the effect you are looking for.
In the route, you can define if these queryParams will replace the url, or if it will refresh the model.
Use the transitionToRoute, when you wish to switch to a different route, or different model.
App.CresShowResultController = Ember.ArrayController.extend({
queryParams: ['county'],
county: null,
actions: {
displayQueryData: function(){
this.set('county', 'someCounty');
// this.transitionTo({queryParams: {county: 'someCounty'}});
},
},
});

How to get the type of route path in Ember

If I have in the router map:
this.resource('detail', { path: '/detail/:type' }, function() {
...
});
And I retrive the currentPanth in my Ember Application code:
currentPath: '',
ApplicationController : Ember.Controller.extend({
updateCurrentPath: function() {
App.set('currentPath', this.get('currentPath'));
console.log('currentPath',App.currentPath);
}.observes('currentPath')
}),
When I navigate in my app, I get the route names by console, but when It is "detail" I get "detail.index". How can I get the type?
you only have access to the params in the route, ie. when you are defining your model:
App.Router.map(function() {
this.resource('photo', { path: '/photos/:photo_id' });
});
App.PhotoRoute = Ember.Route.extend({
model: function(params) {
return Ember.$.getJSON('/photos/'+params.photo_id);
}
});
Or you can also use paramsFor, also in the route only.
Depending on what you are trying to acomplish maybe query params suit better

Categories

Resources