I am trying to create a route for a user profile page, but when I visit the route it shows up as a completely blank page and with no errors in the terminal. Nothing whatsoever is shown, including static HTML. Here's the code:
routes.js
Router.route('/user/:_id', function () {
this.render('user');
}, {
name: 'user',
data: function(){
return Users.findOne({_id: this.params._id})
}
});
user.html
<template name="user">
<p>hello</p>
</template>
At the moment, I am using the default user accounts package and have not added any publication or subscription code.
Are you sure Users is an existing collection?
At the moment, I am using the default user accounts package and have
not added any publication or subscription code.
In that case, with autopublish enabled, your problem is probably solved by changing
data: function(){
return Users.findOne({_id: this.params._id})
}
into:
data: function(){
return Meteor.users.findOne({_id: this.params._id})
}
although it's strange this doesn't throw an error in your console...
Not sure if this is the reason, but I think that with multiple options for the route, you should incapsulate this.render in an action parameter. Something like this:
Router.route('/user/:_id', {
name: 'user',
data: function() {
return Users.findOne({_id: this.params._id})
},
action: function () {
this.render('user');
}
});
Source
I get an error in the terminal: "Users is not defined":
http://meteorpad.com/pad/eciFidhwHmLhjWmF3/Leaderboard
In your data function, try substituting Meteor.users.findOne({_id: this.params._id})
If you fix the HackPad I listed, Meteor.users won't work since the current version of HackPad doesn't support a late enough version of Meteor with Meteor.users. However, if you comment out your data function, you should at least see the page.
Related
i am struggling with adding in pagination for my forums. Could you help me out? Basically, I was expecting on my forums page, to only see 10 posts. but it is returning all of them. The "Load More" button also does nothing (it seems like).
I am using this package: Paginated Subscription
Here is the code I am using:
if (Meteor.isClient) {
Deps.autorun(function() {
var handle = Meteor.subscribeWithPagination('posts',10);
});
Template.postsList.helpers({
'posts': function(){
return Posts.find({});
}
});
Template.postsList.events({
'click .btn': function(){
handle.loadNextPage();
}
})
}
if (Meteor.isServer) {
Meteor.startup(function () {
Meteor.publish("posts", function(limit){
return Posts.find({}, {limit: limit});
});
});
}
I don't think the var handle = Meteor.subscribeWithPagination('posts',10); Needs to be in the Deps block unless you are passing some reactive parameter to thehandle.
See this Issue on Github.
You can use Kurounin subscribe based pagination.It works for me.In atmospherejs, there is an another react pagination you can check it in Kurounin repository
I have already answered this kind of pagination to one of question. Please refer the exact code that can help you.
Meteor Pagination Issue
In your publication you must use sort (as documentation says)
// Using sort here is necessary to continue to use the Oplog Observe
Driver!
// https://github.com/meteor/meteor/wiki/Oplog-Observe-Driver
Meteor.publish("posts", function(limit){
return Posts.find({}, {
limit: limit,
sort: {
createdAt: -1
}
});
});
I'm not sure why this code works once in a while and fails other times:
var u = Meteor.users.findOne(username:'john');
console.log(u);
When I go to my page for the first time, sometimes the console.log(u) shows some results. But if I press refresh, console.log(u) shows undefined. I can't consistently reproduce one issue or the other. It seems pretty random when i get undefined or a collection. What's wrong with my code? How do I consistently get a collection for the variable u?
Like Christian Fritz said in comment on your question, it's probably a matter of collection not being fully loaded when your code is executed. If you use iron:router, you can use subscribe or waitOn as described there: http://iron-meteor.github.io/iron-router/#the-waiton-option so the page is loaded only when the collections are ready (meaning they are fully loaded).
You can also put it in a helper or use a Tracker Autorun to detect when your entry is available and then do whatever you want to do with it.
Edit: A sample for iron:router below
// myproject.jsx
var Cars = new Mongo.Collection('cars');
if(Meteor.isServer)
{
Meteor.publish("myCollections", function () {
return Meteor.users.find();
});
Meteor.publish("anotherCollection", function(){
return Cars.find();
});
}
//lib/router.js
Router.route('/my-page', {
name: 'myPage',
layoutTemplate: 'myPage',
waitOn: function() {
'use strict';
return [Meteor.subscribe('myCollection'),Meteor.subscribe('anotherCollection')];
},
data: function() {
'use strict';
return Collection.findOne();
}
});
My Meteor app runs slowly in the beginning for about ten seconds, and then becomes fast again. I am trying to improve the performance but having troubles to find the real cause.
I thought the problem was that I am publishing all the course information like following:
if (Meteor.isServer) {
Meteor.publish("courses", function() {
return Courses.find();
});
}
I tried using Kadira to monitor exactly what's happening. However, looking at the result, I am starting to think maybe it's not the real problem.
If it only takes 292ms for pubsub response time, it shouldn't feel that laggy but I cannot think of any other reason why the app would be so slow in the beginning and become fast again. Can an expert point me to the redirection?
UPDATE:
I could improve the duration of lagginess in the beginning by making the following changes:
in /server/publications.js
if (Meteor.isServer) {
Meteor.publish("courses", function() {
// since we only need these two fields for the search bar's autocomplete feature
return Courses.find({}, {fields: {'catalog':1, 'titleLong':1}});
});
Meteor.publish("courseCatalog", function(catalog) {
// publish specific information only when needed
return Courses.find({"catalog": catalog});
});
}
and in router.js I made changes accordingly so I subscribe based on specific pages. But there's still some lag in the beginning and I wonder if I can make more optimizations, and what is the real cause of the slowness in the beginning.
UPDATE2:
I followed the suggestion and made changes like below:
Session.set('coursesReady', false); on startup.
and in router:
Router.route('/', function () {
Meteor.subscribe("courses", function(err) {
if (!err) {
console.log("course data is ready")
Session.set('coursesReady', true);
}
});
....
and in /lib/helpers.js which returns data for typeahead library
if (Meteor.isClient) {
Template.registerHelper("course_data", function() {
console.log("course_data helper is called");
if (Session.get('coursesReady')) {
var courses = Courses.find().fetch();
return [
{
name: 'course-info1',
valueKey: 'titleLong',
local: function() {
return Courses.find().fetch();
},
template: 'Course'
},
But now the problem is that when the helper function is called, the data is never ready. The console print:
Q: How do I ensure that the helper function is called only after the data is ready, OR called again when the data is ready? Since Session is reactive, shouldn't it be called again automatically?
I can't check this right now, but I believe your issue might be that the course_data helper is being run multiple times before all 1000+ documents in the subscription are ready, causing the typeahead package to re-run some expensive calculations. Try something like this:
/client/views/global/helpers.js
Template.registerHelper("course_data", function() {
if (!Session.get('coursesReady')) return [];
return [ //...
/client/subscriptions.js
Meteor.subscribe("courses", function(error) {
if (!error) Session.set('coursesReady', true);
});
Update:
Really, Meteor's new features this.subscribe() and Template.instance().subscriptionsReady() are ideal for this. Session isn't really the right choice, but it should still be reactively updating (not sure why it isn't for you). Try instead making the following changes to /client/views/navwithsearch.js (and main, though ideally both templates should share a single search template):
Template.NavWithSearch.onCreated(function() {
this.subscribe('courses');
});
Template.NavWithSearch.onRendered(function() {
this.autorun(function() {
if (Template.instance().subscriptionsReady()) {
Meteor.typeahead.inject();
}
});
});
The idea is to tie the lifecycle of the subscription to the view that will actually be using that subscription. This should delay the typeahead injection until the subscription is completely ready.
I'm trying to publish all the usernames to the clients, even if not signed in. For that, on the server I have:
Meteor.publish("users", function() {
return Meteor.users.find({}, {fields : { username : 1 } });
});
And on the client:
Meteor.subscribe("users");
However, when I try to access the Meteor.users collection, I find nothing there.
(This is essentially the same as the question here: Listing of all users in the users collection not working first time with meteor js, only without checking the roles for admin first. Still doesn't seem to work..)
I'm probably missing something silly..
I find the same issue, and after doing a research i find this package, i think it may should help you.
Take a look and hope it help you
Update
First move the subscription to the /lib folder, just to make sure its the first thing meteor do when start, also change a little bit the subscription like this on the /lib, folder.
Tracker.autorun(function() {
if(Meteor.isClient) {
if (!Meteor.user()) {
console.log("sorry you need to be logged in to subscribe this collection")
}else{
Meteor.subscribe('users');
}
}
});
For better security we just subscribe to the users collection when the client its logged in
This code outputs all the usernames to the clients, even if not signed in (in this case on /users page):
server/publications.js:
Meteor.publish("userlist", function () {
return Meteor.users.find({},{fields:{username:1}});
});
client/users_list.js:
Template.usersList.helpers({
users: function () {
return Meteor.users.find();
}
});
client/users_list.html:
<template name="usersList">
{{#each users}}
{{username}}
{{/each}}
</template>
lib/router.js (using iron:router package):
Router.route('/users', {
name: 'usersList',
waitOn: function(){
return Meteor.subscribe("userlist");
}
});
Hope it helps.
I have a /user route set up, which is supposed to render the login template if the current user isn't logged in. The entire router has a waitOn that waits for the currentUser subscription to finish. The problem is that when I go to /user it simply renders the dataNotFound template instead.
Here's the snippets of code that are relevant to this situation. I've been careful to show you them in the order they're defined in my lib/router.js file.
Router.plugin('dataNotFound', {notFoundTemplate: 'notFound'});
Router.onBeforeAction(function () {
console.log(Meteor.userId())
if (!Meteor.userId()) this.render('login');
else this.next();
}, { only: ['user'] });
Router.configure({
waitOn: function () { return Meteor.subscribe('currentUser'); }
});
Router.route('/user', {
name: 'user',
template: 'userView',
data: function () { return Meteor.user(); }
});
That console.log above doesn't even ever fire. It seems to me that since it should be a reactive function that even if initially the dataNotFound is rendered, then soon after that the onBeforeAction should be fired and render the login template, right?
It's very bizarre that your console log doesn't even fire. I have a few ideas, but first want to address the last piece of your question.
The dataNotFound plugin is triggered when the data function fires on your rout. This means it is bypassing your onBeforeAction hook altogether, and not that it isn't getting there.
One thing I can think of that might be worth trying would be wrapping the 'user' route action in a if ( this.ready() ) statement:
edit:
Router.route('user', {
// Your other stuff
action: function() {
if this.ready() {
this.render();
},
The reason I suggest this is just that you are using a waitOn statement, but I'm not 100% sure how that works if you don't have a this.ready() somewhere in your route, because that's what (again, from my reading of the documentation, have not fiddled around with it) tells the router what to wait before executing. Possibly it's not waiting at all right now.
I had a problem with onBeforeAction hook after upgrading from meteor 0.9.1 to 1.
It didnt get fired when it should. Like after I log out, I enter address manually and instead of login page I can see the actual site waiting for data that never comes. onRun hook solved it, but as docs says it gets fired only once.
Router.onRun(function () {
if (!Meteor.userId()) {
this.render('login');
} else {
this.next();
}
}, { only: ['user'] });
Try swapping out Meteor.userId() with Meteor.user() in your if statement. See this link for reference on how to handle checking for the user in a before filter: http://www.manuel-schoebel.com/blog/meteorjs-iron-router-filters-before-and-after-hooks.
I found the issue here.
According to this post, thanks to Steeve Cannon. The problem is on waitOn function.
Probably when you logginOut the subscribe to currentUser will fail, and this will make your app in infinite waiting. onBeforeAction runs after waitOn
You will need to check all variables in you Publish to insure waitOn complete successfully.
Put an if statement inside the waitOn function.
waitOn: function () {
if(Meteor.userId())
return Meteor.subscribe('currentUser');
}
Refer this comment to know why this is happening: https://github.com/iron-meteor/iron-router/issues/1010#issuecomment-72210587