Create a universal helper variable - meteor

Is there a way to create a variable at the top of template helpers to remove duplication.
In this particular situation I'm using var candidate = FlowRouter.getParam('id'); and I have to create the variable in each helper. I assume there is a better way.
professionalOverview: function() {
var candidate = FlowRouter.getParam('id');
return ProfessionalOverview.findOne({ candidateUserId: candidate });
},
candidateImg: function() {
var candidateUserId = FlowRouter.getParam('id');
return Files.findOne({ userId: candidateUserId });
},
EDIT
Template.talentProfileNew.onCreated(function() {
var self = this;
self.autorun(function(){
this.candidateUserId = new ReactiveVar(FlowRouter.getParam('id'));
}
});
Template.talentProfileNew.helpers({
candidate: function() {
console.log(Template.instance().candidateUserId.get());
return Meteor.users.findOne({_id: Template.instance().candidateUserId.get()});
}
});

you could read it once in onCreated() and put it in a reactive var. e.g.
Template.Foo.onCreated(function() {
this.candidateUserId = new ReactiveVar(FlowRouter.getParam('id'));
});
Template.Foo.helpers({
candidateImg() {
return ProfessionalOverview.findOne({ userId: Template.instance().candidateUserId.get()});
}
});

Related

returning embedded document from collection find

This Meteor code tries to return a cursor to the embedded documents referenced by the field data, then checks if it exists (because some times it does not exist in ActiveTaskCol) before returning this template helper method.
added later
The expected returned cursor will be used in the html {{#each data}} for more work hence the use of .find instead of .findOne.
The problem is that the if statement evaluates to true even though there is no data field in the ActiveTaskCol, I also tried obj.count() > 0 which also true even though "data" field does not exist in the collection.
How can I fix this? Thanks
Template.index.helpers({
taskInputs: function () {
var ready = Meteor.subscribe('inputsCol').ready();
var data = InputsCol.find({});
var selectedTask = Session.get('taskSelected');
var obj = ActiveTaskCol.find({action: selectedTask}, {field: {data: 1}});
if (typeof obj != 'undefined') { //<-always true --------------
return {items: obj};
} else {
return {items: data, ready: ready};
}
}
});
It is always true because, you are using find, which returns a cursor. Instead, you should use findOne, so that, it will return document or undefined, if there is no such document. I also suggest, you use obj, which checks for falsy values like undefined, null, false instead of typeof obj != 'undefined'
Template.index.helpers({
taskInputs: function () {
var ready = Meteor.subscribe('inputsCol').ready();
var data = InputsCol.find({});
var selectedTask = Session.get('taskSelected');
var obj = ActiveTaskCol.findOne({action: selectedTask}, {field: {data: 1}});
if (obj) {
return {items: obj};
} else {
return {items: data, ready: ready};
}
}
});
Update:
Based on your comments, you can use obj.count() to check whether there are documents matching your criteria.
Template.index.helpers({
taskInputs: function () {
var ready = Meteor.subscribe('inputsCol').ready();
var data = InputsCol.find({});
var selectedTask = Session.get('taskSelected');
var obj = ActiveTaskCol.find({action: selectedTask}, {field: {data: 1}});
if (obj.count() > 0) {
return {items: obj};
} else {
return {items: data, ready: ready};
}
}
});
Update 2
Template.index.helpers({
taskInputs: function () {
var ready = Meteor.subscribe('inputsCol').ready();
var data = InputsCol.find({});
var selectedTask = Session.get('taskSelected');
var obj = ActiveTaskCol.find({
action: selectedTask,
data: { $exists: true }
}, {
field: {data: 1}
});
if (obj.count() > 0) {
return {items: obj};
} else {
return {items: data, ready: ready};
}
}
});

Pagination with meteor and iron router not re-rendering

I'm really struggling to understand what's going on here. I have a template
<template name="gallery">
<div>
123
</div>
{{#each art}}
{{name}}
{{/each}}
</template>
Then I have routes like this
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
return {
page: page,
};
},
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
return {
page: page,
};
},
});
});
Following this article I'm using template subscriptions like this
var G_PAGE_SIZE = 10;
Template.gallery.onCreated(function() {
var instance = this;
var route = Router.current();
instance.loaded = new ReactiveVar(0);
instance.autorun(function() {
var pageId = parseInt(route.params._page);
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
if (subscription.ready()) {
instance.loaded.set(1);
}
});
instance.art = function() {
return Art.find({});
};
});
Template.gallery.helpers({
art: function() {
return Template.instance().art();
},
});
It works but when I click one of the links changing the route the page doesn't re-render
So ... some other answer on here said that's because there's no reactive connection between data changing on the route through the router and the template.
So I tried use route.state which as a ReactiveDict (not sure where that came from). If it's part of iron:router or if it's part of reactive-var
Anyway I changed the code to
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
this.state.set('page', page); // <------------ADDED
return {
page: page,
};
},
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
this.state.set('page', page); // <------------ADDED
return {
page: page,
};
},
});
});
In the onCreated
Template.gallery.onCreated(function() {
var instance = this;
var route = Router.current();
instance.loaded = new ReactiveVar(0);
instance.autorun(function() {
var pageId = route.state.get('page'); // <--------- CHANGED
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
if (subscription.ready()) {
instance.loaded.set(1);
}
});
instance.art = function() {
return Art.find({});
};
});
Template.gallery.helpers({
art: function() {
return Template.instance().art();
},
});
That doesn't work either except sometimes. In the interest of debugging I added a console.log to the route
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
this.state.set('page', page);
console.log("/root"); // <------------ADDED
return {
page: page,
};
},
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
this.state.set('page', page);
console.log("/gallery/" + page); // <------------ADDED
return {
page: page,
};
},
});
});
Suddenly it starts working !???!#!? I remove the console.logs and it stops
I also tried adding actions without the console.logs
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
this.state.set('page', page);
return {
page: page,
};
},
action: function() { // <- added
var page = 1; // <- added
this.state.set('page', page); // <- added
this.render(); // <- added
}, // <- added
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
this.state.set('page', page);
return {
page: page,
};
},
action: function() { // <- added
var page = parseInt(this.params._page); // <- added
this.state.set('page', page); // <- added
this.render(); // <- added
}, // <- added
});
});
That doesn't work either.
update
So using Router.current().data().??? seems to make it work. It's now this
Router.map(function() {
this.route('/', {
template: 'gallery',
data: function() {
var page = 1;
// <--- removed this.state() stuff
return {
page: page,
};
},
// <---- removed action stuff
});
this.route('/gallery/:_page', {
template: 'gallery',
data: function() {
var page = parseInt(this.params._page);
// <--- removed this.state() stuff
return {
page: page,
};
},
// <---- removed action stuff
});
});
helper
Template.gallery.onCreated(function() {
var instance = this;
instance.loaded = new ReactiveVar(0);
instance.autorun(function() {
var route = Router.current(); // <----- Moved from 3 lines up
var pageId = route.data().page; // <--------- CHANGED
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
if (subscription.ready()) {
instance.loaded.set(1);
}
});
instance.art = function() {
return Art.find({});
};
});
Template.gallery.helpers({
art: function() {
return Template.instance().art();
},
});
No idea if this is now correct or if I'm just getting lucky like with the console.log editions
My guess is that your autorun function is not being re-run because you are not using any reactive variables. I'm not sure if Router.current() or Router.current().data() are reactive, but if they're not, then this explains the issue clearly for me. To test this, try putting some console logging in your autorun function.
Now, I would proposed some revisions that may work for you.
Routing code
Redirect to '/' URL to '/gallery/1' so you can re-use routing code
Router.route('/', function(){
this.redirect('/gallery/1');
});
Sending the page number in the data object to your template is important so that we can use this object in our autorun function
Router.route('/gallery/:_page', {
template: 'gallery',
data: function() {
return {
page: this.params._page,
};
}
});
Also, you don't need to use parseInt method unless you are trying to re-route or handle that exception in your routing code.
Gallery onCreated and helpers
There is a Template.subscriptionsReady helper provided by Meteor so you don't have to manually check if the subscription is loaded unless you really want it. Here's the Template.subscriptionsReady documentation
Here's a simplified version of your onCreated method using the template.data object which was built by the routing code above. Using the autorun wrapper is important so that it will re-run when template.data is changed by your router.
var G_PAGE_SIZE = 10;
Template.gallery.onCreated(function() {
var instance = this;
instance.autorun(function() {
// access the data object built by your route code
var pageId = instance.data.page;
var page = pageId - 1;
var skip = page * G_PAGE_SIZE;
instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
});
});
Define access to your reactive data sources using the template.helpers method.
Template.gallery.helpers({
art: function() {
return Art.find({});
}
});
Note: Not necessary to define your helper in the onCreated and template.helpers

Meteor. Problems with subscribe/publish

i have a problem.
I'm trying to build highcharts graphic.
How it works:
I'm going to my route ('ship.details'), and here i have not problems.
My problem:
subsription to (ships_snapshots_all) not working.
My publish.js:
Meteor.publish("ships_snapshots", function(user, options) {
if(!this.userId) return null;
if(this.userId) {
console.log('subsribed by ' + user);
return ships_snapshots.find({userId: user}, options);
}
});
Meteor.publish("ships_snapshots_all", function() {
return ships_snapshots.find({});
})
My subscribe.js (in lib folder):
Meteor.subscribe('ships_snapshots');
Meteor.subscribe('ships_snapshots_all');
Problem 100% in my subsription, because if i'm installing autopublish all working good. And problem in my router i think.
router.js:
Router.route('/ships/details', {
name: 'ship.details',
loadingTemplate: 'loading',
onBeforeAction: function() {
var shipId = Session.get('currentShipId');
if(!shipId) {
Router.go('user.ships');
} else {
this.next();
}
},
waitOn: function() {
if (Meteor.isClient) {
var getCompare = Meteor.user().profile.wows.compareWith;
console.log(getCompare);
var user2 = Meteor.users.findOne({"profile.wows.nickname": getCompare});
var user2Id = user2._id;
if (getCompare) {
var user2 = Meteor.users.findOne({"profile.wows.nickname": getCompare});
if (user2) {
var user2Id = user2._id;
}
}
if (getCompare) {
var handle = Meteor.subscribe('ships_snapshots', Meteor.user()._id) && Meteor.subscribe('ships_snapshots', user2Id) && Meteor.subscribe('userSearchInfo', getCompare);
Session.set('compareWith', user2);
console.log('user2 _____');
console.log(user2);
return handle
} else {
var handle = Meteor.subscribe('ships_snapshots', Meteor.user()._id) && Meteor.subscribe('ships_snapshots', user2Id);
return handle
}
}, data: function() {
if (handle.ready()) {
var shipname = this.params.shipName;
var obj = {};
var query = ships.findOne();
var shipId = Session.get('currentShipId');
var result;
_.each(Meteor.user().profile.wows.ships, function(row) {
if (row.ship_id === shipId) {
result = row;
}
});
return result;
}
}
});
I think my problem in subscripion for ship_snapshots. Something going wrong here, but i can't to resolve this problem.
What exactly do you mean by "not working"? From your code I would assume that you're always seeing all the ship snapshots.
You shouldn't have the subscribes in /lib if you have them in your router. If you have Meteor.subscribe('ships_snapshots_all'); in /lib then you should always be seeing all the ship snapshots (assuming you're not stopping that subscription anywhere).
Also your subscription to all should be:
Meteor.publish("ships_snapshots", function(user, options) {
if(this.userId) {
console.log('subsribed by ' + user);
return ships_snapshots.find({userId: user}, options);
} else this.ready();
});
You don't want to return null when there is no user, you can just mark the subscription as ready without finding any records. This is not the cause of your problem but just good practice.
Meteor.publish("ships_snapshots", function(user, options) {
if(!this.userId) return null;
if(this.userId) {
console.log('subsribed by ' + user);
return ships_snapshots.find({userId: user._id}, options);
}
});
In your publish script, is user really an id or is it a user object? I changed it to user._id. Please check that.

Meteor define ReactiveVar to be accesible in .events and .helpers

I am trying to define a new ReactiveVar variable to be accessible in all the template sections (ex. .events, .helpers, .rendered ...etc) as shown in my code below, yet I am always getting an error:
Error: Exception in template helper:
ReferenceError: logData is not defined
Can someone please tell me what I am missing / doing wrong here? Thanks
Code:
Template.detailedreport.rendered = function() {
var logData = new ReactiveVar;
logData.set([]);
};
Template.detailedreport.helpers({
myCollection: function () {
return logData.get();
}
});
Template.detailedreport.events({
'submit form': function(e) {
e.preventDefault();
var now = Session.get("startDate");
var then = Session.get("endDate");
var custID = Session.get("customer");
var projID = Session.get("project");
Meteor.call('logSummary', now, then, projID, custID, function(error, data){
if(error)
return alert(error.reason);
logData.set(data);
});
}
});
You need to define the ReactiveVar on the template instance like this :
Template.detailedreport.created = function() {
this.logData = new ReactiveVar([]);
};
Then you'll be able to access it in helpers like this :
Template.detailedreport.helpers({
myCollection: function () {
return Template.instance().logData.get();
}
});
In events you can use the template argument :
Template.detailedreport.events({
'submit form': function(e, template) {
e.preventDefault();
var now = Session.get("startDate");
var then = Session.get("endDate");
var custID = Session.get("customer");
var projID = Session.get("project");
Meteor.call('logSummary', now, then, projID, custID, function(error, data){
if(error){
return alert(error.reason);
}
template.logData.set(data);
});
}
});

Meteor data not inserting or displaying after removing insecure package

Data is not getting inserted into the database after i removed autopublish and insecure packages. Please let me know what i am missing.
Userdata = new Meteor.Collection("Userdata");
if (Meteor.isClient) {
Template.sample.events({
"click button.clickeve": function (){
var e_value = $('input[name = "exampleInputEmail1"]').val();
var e_name = $('input[name = "exampleInputName"]').val();
doc = {user_id: Meteor.userId(), e_value:e_value, e_name:e_name}
}
});
Template.temp.list_item = function(){
return Userdata.find();
}
Meteor.subscribe("Userdata");
}
if (Meteor.isServer) {
Meteor.publish("Userdata", function() {
return Userdata.find();
});
Userdata.allow({
insert: function(userID,doc) {
return userID === doc.user_id;
}
});
}
You don't have an insert statement.
Userdata = new Meteor.Collection("Userdata");
if (Meteor.isServer) {
Meteor.publish("Userdata", function() {
return Userdata.find();
});
Userdata.allow({
insert: function(userID,doc) {
return userID === doc.user_id;
}
});
}
if (Meteor.isClient) {
Template.sample.events({
"click button.clickeve": function (e){
e.preventDefault(); // to prevent default action of the button
var e_value = $('input[name = "exampleInputEmail1"]').val();
var e_name = $('input[name = "exampleInputName"]').val();
doc = {user_id: Meteor.userId(), e_value:e_value, e_name:e_name};
Userdata.insert(doc); // actually inserting the document
}
});
Template.temp.list_item = function(){
return Userdata.find();
}
Meteor.subscribe("Userdata");
}

Resources