Reference blaze helper function in second helper - meteor

I would like to access blaze helper functions within a second helper function. I'm not sure what I'm doing wrong here.
Template.example.helpers({
functionOne: function (){
return { min: salMin, max: salMax, sal: salary };
},
functionTwo: function (){
var one = functionOne.min;
var two = functionOne.max;
return one - two;
},
});

HTML CODE: you can pass the returned values from helper functionOne to functionTwo
{{#with functionOne}}
{{functionTwo min max}}
{{/with}}
Helper Code:
Template.example.helpers({
functionOne: function (){
var salMin = 20;
var salMax = 100;
var salary = 90;
return { min: salMin, max: salMax, sal: salary };
},
functionTwo: function (min, max){
return min - max;
},
});

Related

Create a universal helper variable

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()});
}
});

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};
}
}
});

Get value returned from another method

In a Template helper, is it possible to get from a method a value returned by another method?
In example
Template.postsList.helpers({
posts: function () {
return Posts.find({});
},
nextPath: function () {
// how to return here the number of posts from the query
// in the posts method?
}
});
You can just refactor the code so you have a shared way to obtain the posts cursor:
var postsCursor = function() {
return Posts.find();
};
Template.postsList.helpers
posts: postsCursor,
nextPath: function () {
var count = postsCursor().count();
// do something with count
}
});

FullCalendar renders a single event only

I'm trying to write a simple app based on FullCalendar package. When I run the code, none of the events is rendered, however right after clicking a day, an event gets shown on that day. If I click another day right after, it will erase the last one, and show the most recent one.
CalEvents = new Mongo.Collection("calevents");
// to be used later to handle editing
if (Meteor.isClient) {
Session.setDefault("event2edit", null);
Session.setDefault("showEditWindow", false);
Session.setDefault("lastMod", null);
Router.route('/', function () {
this.render('home');
});
Router.route('/calendar', function () {
this.render('calendar');
});
// runs when page has been rendered
Template.calendar.rendered = function () {
$('#calendar').fullCalendar({
events: function (start, end, timezone, callback) {
var events = [];
calEvents = CalEvents.find();
calEvents.forEach(function (evt) {
events.push({
id: evt._id,
title: evt.title,
start: evt.start,
end: evt.end
});
});
//alert(events.length);
callback(events);
},
dayClick: function(date, jsEvent, view){
CalEvents.insert({title:'NEW', start:date, end:date});
Session.set('lastMod', new Date());
updateCalendar();
},
eventClick: function (calEvent, jsEvent, view) {
}
});
}
Template.calendar.lastMod = function () {
return Session.get('lastMod');
}
}
var updateCalendar = function(){
$('#calendar').fullCalendar( 'refetchEvents' );
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
Is it a bug? Or is my code missing something? Thank you.
Try to pack your
$('#calendar').fullCalendar({
into a variable, like
calendar = $('#calendar').fullCalendar({
and add the following closing of your calendar function:
}).data().fullCalendar
and insert the Tracker.autorun function at the end of your Template.calendar.rendered block:
Template.calendar.rendered = function () {
calendar = $('#calendar').fullCalendar({
events: function (start, end, timezone, callback) {
var events = [];
calEvents = CalEvents.find();
calEvents.forEach(function (evt) {
events.push({
id: evt._id,
title: evt.title,
start: evt.start,
end: evt.end
});
});
//alert(events.length);
callback(events);
},
dayClick: function(date, jsEvent, view){
CalEvents.insert({title:'NEW', start:date, end:date});
Session.set('lastMod', new Date());
updateCalendar();
},
eventClick: function (calEvent, jsEvent, view) {
}
}).data().fullCalendar
Tracker.autorun(function(){
allReqsCursor = CalEvents.find().fetch();
if(calendar) calendar.refetchEvents();
});
};
Additionally, for increase in Performance:
For-Loop vs forEach Loop
You might consider using the for-loop instead of forEach-loop as former is 10 to 40 times faster, especially with pre-cached parameters i and len:
forEach Loop: (Originally)
calEvents = CalEvents.find();
calEvents.forEach(function(evt) {
events.push({
id: evt._id,
title: evt.t,
start: evt.s,
end: evt.e,
});
});
callback(events);
For loop: (10 to 40 times faster with pre-cached parameters i and len)
calEvents = CalEvents.find().fetch();
var len = calEvents.length, i = 0; //pre-cache the i and len
for(i; i < len; i++){
events.push({
id: calEvents[i]._id,
title: calEvents[i].t,
start: calEvents[i].s,
end: calEvents[i].e,
});
};
callback(events);
Hope this helps.

Meteor.js calling a template.helpers function vs global variable

I am using Reactive-table to display paginated data in my meteor.js app as shown below, yet data displayed in Reactive-table is dependent on on specific user event (Selecting client, project, date range and clicking on the submit button). So I was wondering if it is possible to trigger template.helpers >> myCollection function from the 'submit form' event? OR is it better to define a global variable to store data returned from user query based on the user (client, project, date range selection) then make this global variable the return from the myCollection function?
I have tried researching how to call .helpers function from an template.events event but couldn't find any information. So any help on which approach is better and if calling the .events function is better then how to do that, will be highly appreciated. Thanks.
Below is the code I have in my app:
Template.detailedreport.rendered = function() {
Session.set("dreport_customer", "");
Session.set("dreport_project", "");
Session.set("dreport_startDate", new Date());
Session.set("dreport_endDate", new Date());
$('.set-start-date').datetimepicker({
pickTime: false,
defaultDate: new Date()
});
$('.set-end-date').datetimepicker({
pickTime: false,
defaultDate: new Date()
});
$('.set-start-date').on("dp.change",function (e) {
Session.set("dreport_startDate", $('.set-start-date').data('DateTimePicker').getDate().toLocaleString());
});
$('.set-end-date').on("dp.change",function (e) {
Session.set("dreport_endDate", $('.set-end-date').data('DateTimePicker').getDate().toLocaleString());
});
};
Template.detailedreport.helpers({
customerslist: function() {
return Customers.find({}, {sort:{name: -1}});
},
projectslist: function() {
return Projects.find({customerid: Session.get("dreport_customer")}, {sort:{title: -1}});
},
myCollection: function () {
var now = Session.get("dreport_startDate");
var then = Session.get("dreport_endDate");
var custID = Session.get("dreport_customer");
var projID = Session.get("dreport_project");
Meteor.call('logSummary', now, then, projID, custID, function(error, data){
if(error)
return alert(error.reason);
return data;
});
}
},
settings: function () {
return {
rowsPerPage: 10,
showFilter: true,
showColumnToggles: false,
fields: [
{ key: '0._id.day', label: 'Day' },
{ key: '0.totalhours', label: 'Hours Spent'}
]
};
}
});
Template.detailedreport.events({
'submit form': function(e) {
e.preventDefault();
var now = $('.set-start-date').data('DateTimePicker').getDate().toLocaleString();
var then = $('.set-end-date').data('DateTimePicker').getDate().toLocaleString();
var custID = $(e.target).find('[name=customer]').val();
var projID = $(e.target).find('[name=project]').val();
//Here is the problem as I am not sure how to refresh myCollection function in .helpers
},
'change #customer': function(e){
Session.set("dreport_project", "");
Session.set("dreport_customer", e.currentTarget.value);
},
'change #project': function(e){
Session.set("dreport_project", e.currentTarget.value);
}
});
Template:
<div>
{{> reactiveTable class="table table-bordered table-hover" collection=myCollection settings=settings}}
</div>
Server:
Meteor.methods({
logSummary: function(startDate, endDate, projid, custid){
//Left without filtering based on date, proj, cust for testing only...
return Storylog.find({});
}
});
Template helpers are reactive, meaning that they will be recomputed if their dependencies change. So all you need to do is update their dependencies and then the myCollection helper will be recomputed.
Replace your comment // Here is the problem... with:
Session.set('dreport_endDate', then);
Session.set('dreport_startDate', now);
Session.set('dreport_project', projID);
Session.set('dreport_customer', custID);

Resources