this._id undefined in Meteor - javascript

I am trying to set my selectedDocId upon routing to a page, but Meteor is throwing undefined . I am using an onBeforeAction in an attempt to store the id that is concatenated at the end of my url via /:id, but I can't get them aligned.
Router.route('speaker', {
path:'/speakers/:_id',
template: 'speaker',
data: function(){
return Speakers.findOne(this.params._id);
},
onBeforeAction: function(){
console.log('speaker route has run');
Session.set('selectedDocId', this._id);
//returns undefined
console.log(this._id);
this.next();
}
});
Template.speaker.helpers({
editingDoc: function(){
return Speakers.findOne({_id: Session.get('selectedDocId')});
}
});

Instead of this._id, use this.params._id just like you did in the data hook.

Related

Meteor Iron Router WaitOn Subscription

I am really struggling with waiting on a subscription to load for a specific route before returning the data to the template. I can see on from the publish on the server that a document is found, but on the client there is no document.
If I do a find().count() on the publish, it shows 1 document found, which is correct, but when I do the count on the subscription, it shows 0 documents.
I have tried a number of different methods, like using subscriptions:function() instead of waitOn:function(), but nothing works.
Collections.js lib:
SinglePackage = new Mongo.Collection("SinglePackage");
SinglePackage.allow({
insert: function(){
return true;
},
update: function(){
return true;
},
remove: function(){
return true;
}
});
Publications.js server:
Meteor.publish("SinglePackage", function(pack_id) {
return Packages.find({shortId: pack_id});
});
Iron Router:
Router.route('/package/:id', {
name: 'package.show',
template: 'Package_page',
layoutTemplate: 'Landing_layout',
waitOn: function() {
return Meteor.subscribe('SinglePackage', this.params.id);
},
data: function() {
return SinglePackage.find();
},
action: function () {
if (this.ready()) {
this.render();
} else {
this.render('Loading');
}
}
});
Am I doing something very wrong, or is this just a complicated thing to achieve? One would think that waitOn would make the rest of the function wait until the subscription is ready.
Any help would be highly appreciated.
It appears that the data function is running before the subscription is ready. Even if the data function did run after the subscription was ready, it wouldn't be a reactive data source rendering the pub/sub here pointless. Here's a great article on reactive data sources.
Referring to the example from the Iron Router Docs for subscriptions, you would do something like this:
Router.route('/package/:id', {
subscriptions: function() {
// returning a subscription handle or an array of subscription handles
// adds them to the wait list.
return Meteor.subscribe('SinglePackage', this.params.id);
},
action: function () {
if (this.ready()) {
this.render();
} else {
this.render('Loading');
}
}
});
Then in your template.js:
Template.Package_page.helpers({
singlePackage() {
// This is now a reactive data source and will automatically update whenever SinglePackage changes in Mongo.
return Package.find().fetch();
}
});
In your template.html you can now use singlePackage:
<template name="Package_page">
{#with singlePackage} <!-- Use #each if you're singlePackage is an array -->
ID: {_id}
{/with}
</template>

How to get the 'keyword' in domain.com/keyword with Iron Router

I am working on a site where I have to search in the DB for string that come after the / on the root domain. I can't find anything about it in the documentation.
I am trying to make it work with Iron Router but any other suggestion would work out.
Thanks for the help!
Edit: Basically I just want to pass anything that comes after domain.com/ to a variable.
Here's something i've been doing so maybe it'll lead you down the right path
Route sends URL params to ownedGroupList template
Router.route('/users/:_id/groups', {
name: 'owned.group.list',
template: 'ownedGroupList',
data: function() {
return {params: this.params};
}
});
Template ownedGroupList can access params object using this.data in onCreated, onRendered, and onDestroyed template event handlers
Template.ownedGroupList.onCreated(function(){
this.subscribe("owned-groups", this.data.params._id );
});
Template ownedGroupList can access params through this variable in helper methods
Template.ownedGroupList.helpers({
groups: function() {
return Groups.find({owner: this.params._id });
}
});
Template ownedGroupList can access params through template.data variable in event handlers
Template.ownedGroupList.events({
'click .a-button': function(event, template) {
var group = Groups.findOne({owner: template.data.params._id });
// do something with group
}
});
Here's a simple route that should do the trick
Router.route('/:keyword', {
name: 'keyword',
template: 'keywordTemplate',
data: function() {
return this.params.keyword;
}
});
This will pass the keyword as the data context to your template and then you can do whatever you want with it. Alternatively you can perform the search straight in the router (especially if you're passing the keyword to a subscription so that the search runs on the server). For example:
Router.route('/:keyword', {
name: 'keyword',
template: 'keywordTemplate',
waitOn: function(){
return Meteor.subscribe('keywordSearch',keyword);
},
data: function() {
return MyCollection.find();
}
});
This second pattern will send your keyword to a subscription named keywordSearch that will execute on the server. When that subscription is ready, the route's data function will run and the data context passed to your keywordTemplate will be whatever documents and fields have been made available in MyCollection.

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!

Meteor this.params._id is undefined based upon ":_id?"

I have a game that I know works properly with an ID per the code on the client side. For example if I were to use the below with {{game._id}} it works properly:
Template.gamePage.game = function() {
return GameCollection.findOne({current: true});
};
However, I am trying to gain access to the publications of 'submissions; only for the specific game ID. Console log below returns undefined.
router.js
this.route('gamePage', {
path: '/games/:_id?',
waitOn: function() {
console.log(this.params._id);
return [
Meteor.subscribe('randomQuestions', Random.id()),
Meteor.subscribe('submissions', this.params._id)
];
}
});
I suspect that params._id pulls from games/:_id, however, I would like it so that that it remains games/:_id? so that I do not have an unnecessary long address.
Any thoughts on why I am getting undefined for params._id
I think you have one button for to access a game, for example...
Tracker.autorun(function () {
Session.set('gameCurrent');
});
Template.gamePage.helpers({
allGames: function(){
return GameCollection.find({});
},
getCurrentGame:function(){
return Session.get('gameCurrent');
}
})
// with this action you access a the route with the id specified
Template.gamePage.events({
'click button#game' : function(event,template){
Session.set('gameCurrent',this._id);
Router.go('editEmail',{_id:this._id})
}
})
Remember that Session only works in the client.

Meteor.user().profile returns 'profile' undefined

I have a helper called 'isActive' and a template named 'create'.. see below
Template.create.isActive = function () {
return Meteor.user().profile.isActive;
};
When I try to run this code it returns the following in console: "Exception in template helper: TypeError: Cannot read property 'profile' of undefined".
Basically I want to pull the 'isActive' info from the current user profile and return it to the template. Any idea why this does not work?
Update
//startup on server side:
Meteor.publish("userData", function() {
if (this.userId) {
return Meteor.users.find({_id: this.userId},
{fields: {'profile.isActive': 1}});
} else {
this.ready();
}
});
//startup on client side
Meteor.subscribe('userData');
//router
this.route('list', {
path: 'list',
waitOn : function () {
return Meteor.subscribe('userData');
},
data : function () {
return Meteor.users.findOne({_id: this.params._id});
},
action : function () {
if (this.ready()) {
this.render();
}
}
});
Meteor.user() is undefined. You are either not logged in with any user or your template is rendered before the users collection is synced to the client. If you use a router like iron router you can wait for the collection being available or for the user being logged on.
Without using a router the easiest would be to check if the user is defined:
Template.create.isActive = function () {
return Meteor.user() && Meteor.user().profile.isActive;
}
Since Meteor.user() is reactive the template will be rerendered when the user changes, i.e. when it is available.
This is a common error btw, see also:
Meteor.user() Error: Uncaught TypeError: Cannot read property 'name' of null
How can I prevent Meteor.user()'s timing hole?

Categories

Resources