SubsManager with Iron-Router new API - meteor

any idea how I could connect SubsManager with IR new API?
I use syntax like:
Router.route('/', function () {
this.subscribe('some_subscription').wait();
if (this.ready()) {
//something
} else {
//something
}
},{
name:'1234'
});
Tried subs.subscribe('some_subscription').wait(); but it threw error
Template never rendered, did you forget to call 'this.next()?(of course I initialized object subs)

From the subscription manager docs https://github.com/meteorhacks/subs-manager/#limitations
At the moment, the following functionality doesn't work (patches welcome):
.........................
...............
chained .wait() call in Iron Router (issue - you can use waitOn instead)
so subs.subscribe('some_subscription').wait(); this will throw error
From Iron-router docs https://github.com/EventedMind/iron-router#migrating-from-094
onRun and onBeforeAction hooks now require you to call this.next(), and no longer take a pause() argument. So the default behaviour is reversed. For example, if you had:
Router.onBeforeAction(function(pause) {
if (! Meteor.userId()) {
this.render('login');
pause();
}
});
You'll need to update it to
Router.onBeforeAction(function() {
if (! Meteor.userId()) {
this.render('login');
} else {
this.next();
}
});
Make sure that this.next() is called on onRun and onBeforeAction blocks
and also organize your router code like in lib/routes.js file
//configuration
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
notFoundTemplate: 'error'
});
//keep all your routers under a common function
Router.map(function() {
this.route("index",{
path:"/",
onBeforeAction:function(){ //do something },
data:return something,
onAfterAction
});
});
Finally my answer to the question any idea how I could connect SubsManager with IR new API?
Router.map(function() {
this.route("index",{
path:"/",
waitOn: function() {
return subs.subscribe('some_subscription');
},
data:function(){
if (this.ready()) {
//do something like this.render("loading")
} else {
//do something this.render("mytemplate")
}
},
onAfterAction
});
});

Related

Meteor Publications/Subscriptions not working

I'm a bit of a noob and having a bit of trouble getting my publications to work. In my data, I have a number of patients and would like to show the data of a single patient. This is how I have structured my publication:
Meteor.publish('patients.single', function (patientId) {
check(patientId, String);
return Patients.find({_id: patientId});
});
and this is how I have subscribed:
Router.route('/patients/:_id', {
layoutTemplate: 'ApplicationLayout',
yieldRegions: {
'single_patient': {to: 'content'}
},
subscriptions: function () {
return Meteor.subscribe('patients.single', this.params._id);
}
});
I have also tried to subscribe via the actual template to no avail:
Template.patient_details.onCreated(function () {
this.subscribe('patients.single', Session.get("currentPatient"));
});
Publications seem easy in theory, but I just can't seem to get them right. What am I doing wrong here?
It takes time for the subscription to get the data from the server to the mini mongo, so you have to wait for the subscription to be ready, before using the data that It will get for you.
If you are using Iron Router try using waitOn instead of subscribe, that will force the router to wait for the subscription to be ready and will render the loading template while its getting the subscription data.
Router.route('/patients/:_id', {
layoutTemplate: 'ApplicationLayout',
yieldRegions: {
'single_patient': {to: 'content'}
},
waitOn: function () {
return Meteor.subscribe('patients.single', this.params._id);
}
data: function () {
return Patients.findOne({_id: this.params._id});
},
});
You can also use the data property, that way you will have the data available in your template instance.data.
Try this:
Server side Js
Meteor.publish('patients.single', function (patientId) {
check(patientId, String);
return Patients.find({_id: patientId});
});
Router JS File
Router.route('/patients/:_id', {
layoutTemplate: 'ApplicationLayout',
yieldRegions: {
'single_patient': {to: 'content'}
},
waitOn: function () {
return Meteor.subscribe('patients.single', this.params._id);
}
});
In client JS File
Template.patient_details.helpers({
getData : function(){
return Collection.find().getch();
});
Don't forget to call the {{getData}} in the template html file.

Proper syntax for iron-router's Router.route?

I have the following code for my iron-router signOut route in a Meteor JS app. I am trying to convert the deprecated Router.map to the new Router.route syntax but having difficulty getting the onBeforeAction and onAfterAction to work. What is the proper Router.route syntax for the following code block?
Router.map(function () {
// sign-out the user then redirect them to the home page
this.route('signOut', {
path: '/sign-out',
onBeforeAction: function () {
if (Meteor.userId()) {
Meteor.logout()
}
this.next();
},
onAfterAction: function () {
this.redirect('/');
}
});
});
Router.route('/sign-out', function() {
//here you put things you wanna render, it's empty since you just want to logout and redirect
}, {
name: 'signOut',
onBeforeAction: function () {
if (Meteor.userId()) {
Meteor.logout()
}
this.next();
},
onAfterAction: function () {
Router.go('/');
}
});
And I think you should add waitOn function, cause there might be no Meteor.user() object at first if not subscribed earlier

MeteorJS, iron-router, filters, redirection, delay

Router._filters = {
isLoggedOut: function (pause) {
if (!Meteor.userId()) {
return this.redirect('home');
} else {
this.next();
}
},
isLoggedIn: function (pause) {
if (Meteor.userId()) {
return this.redirect('dashboard');
} else {
this.next();
}
}
};
filters = Router._filters;
Router.onBeforeAction(filters.isLoggedOut, { except: [
'home'
]});
Router.onBeforeAction(filters.isLoggedIn, { only: [
'home'
]});
I'd like to make filter in iron-router which makes redirect to 'home' when user is not logged in and to 'dashboard' if user is logged in. Everything works, but in the first case dashboard is shown for a second and then redirect is done. How can I get rid of this delay?
I would create a custom controller.
// Global Router configuration
Router.configure({
loadingTemplate: 'loading'
notFoundTemplate: 'notFound'
controller: BaseController
});
The code above says: "For all existing paths, use the BaseController"
Your BaseController should look like this
BaseController = RouteController.extend({
action: function() {
if(!Meteor.userId()) {
// this.render('home');
// this.go('home);
this.redirect('home');
}
else {
// this.render('dashboard');
// this.go('dashboard');
this.redirect('dashboard');
}
}
})
If you need more controll for each site,give your specific site a controller, which inherit from the BaseController. It should looks like this
// Global Router configuration
// Remove the controller property!
Router.configure({
loadingTemplate: 'loading'
notFoundTemplate: 'notFound'
});
Router.map(function() {
this.route('contact', {
path: '/contact',
controller: 'ContactController'
})
});
Your ContactController should looks like this
ContactController = BaseController.extend({
// Do something with this given route,
// e.g., give it a name property or so
name: 'contact',
action: function() {
}
})
For more information, check the Iron.Router guide.
https://github.com/EventedMind/iron-router/blob/devel/Guide.md#route-controllers

struggling to wait on subscriptions and multiple subscriptions

i am really struggling with the iron-router waitOn.
I have a number of subscriptions that i would like to waitOn, it doenst seem to me that iron router is waiting on anything.
I have setup a number of subscriptions (main.js), which i would like to load before the application starts:
Meteor.subscribe("appointments");
Meteor.subscribe("business");
Meteor.subscribe("clients");
Meteor.subscribe("staff");
I have tried almost every configuration i possibly can but i cannot seem to get the "loader" to show itself and wait till all the subscriptions are ready. I have a helper function in the layoutTemplate ('layout') to get a value from the database however findOne() returns undefined/null i assume this is because the router has not waited on the subscriptions...
My router configuration. I would like to understand how i can chain the dependencies or create the dependencies to wait.
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function () {
console.log('Iron router start');
this.subscribe('clients').wait();
this.subscribe('staff').wait();
this.subscribe('appointments').wait();
this.subscribe('business').wait();
this.subscribe('calendar').wait();
},
action: function() {
if (this.ready()) {
this.render('dashboard');
} else {
this.render('loading');
}
}
});
Try changing the waitOn section like this. Also, I think you can remove the subscriptions from the main.js file and write the required/dependent subscriptions in the router's waitOn function for that particular route.
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
waitOn: function () {
console.log('Iron router start');
return [
Meteor.subscribe('clients'),
Meteor.subscribe('staff'),
Meteor.subscribe('appointments'),
Meteor.subscribe('business'),
Meteor.subscribe('calendar')
]
},
action: function() {
if (this.ready()) {
this.render('dashboard');
} else {
this.render('loading');
}
}
});
Try moving your subscriptions from onWait into onBeforeAction:
This may work, but i'm not sure. Usually you define the wait params per route not as a global.
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
onBeforeAction: function () {
console.log('Iron router start');
this.subscribe('clients').wait();
this.subscribe('staff').wait();
this.subscribe('appointments').wait();
this.subscribe('business').wait();
this.subscribe('calendar').wait();
}
});
Router.onBeforeAction('loading');
If this gives you trouble, try using the onBeforeAction above for each of your routes.

Data not accessible in helper block in Meteor

I have autopublish on.
Template.play.helpers ({
title: function () {
wcount = Workouts.find().count();
console.log(wcount);
}
});
This gives me 0.
But if I'm in the developer console of my browser.
Workouts.find().count()
24
I have recently upgraded to 0.8
If I add waitOn to the Router then I get this behavior every other time I load the page.
Router.map(function() {
this.route('splash', {path: '/'});
this.route('play', {
path: '/play',
template: 'play',
waitOn: function() {
return Meteor.subscribe('Workouts')
}
});
After some help from #Christian Fritz it seems that my problem is that its not waiting on my subscription and if the helper doesn't return anything because its undefined then it doesn't get rerun when the data does get loaded.
I have now turned off autopublish. My server/publications.js is:
Meteor.publish('workouts', function() {
return Workouts.find();
});
My router is:
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading'
});
Router.map(function() {
this.route('splash', {path: '/'});
this.route('play', {
path: '/play',
template: 'play',
waitOn: function() {
return Meteor.subscribe('workouts')
}
});
});
in play.js
var workoutsSubcription = Meteor.subscribe('workouts');
console.log("workoutsSubscription.ready() is ",workoutsSubcription.ready());
returns:
workoutsSubscription.ready() is false
once or twice then finally reruns when its fully loaded as true. But shouldn't the waitOn mean that it doesn't run that page until the data is there?
You probably want something like this:
var workoutsSubcription = Meteor.subscribe('workout_count');
Template.play.helpers ({
title: function () {
if(workoutsSubcription.ready()){
wcount = Workouts.find().count();
}
}
});
You would need to publish your subscription on the server as well
Meteor.publish("workout_count", function () {
return Workouts.find();
});

Resources