Collections not showing on page - meteor

I have published a countries collection which I want to show in a table in the countriesList template. So I have added this to the router:
Router.route('/countries_list', {
name: 'countriesList',
waitOn: function() {
return Meteor.subscribe('countries');
},
data: function() {
return Countries.find();
}
});
And this is how the template looks like:
{{#each countries}}
<tr>
<td>{{name}}</td>
</tr>
{{/each}}
But the page stays empty. However, the collection is filled on the client, if I check the browser console and do Countries.findOne();, I get this result:
Object {_id: "WWJhMBne4CiEdbbdg", name: "England"}
So what am I doing wrong here?

You template is making the assumption that the cursor is being stored in coutries. It isn't. It would be if your data hook looked like:
return {countries: Countries.find()};
As your code is written, the cursor is the context for your template so this should work:
{{#each this}}
<tr>
<td>{{name}}</td>
</tr>
{{/each}}

Related

Meteor {{#each in}} not scoping down correctly

I'm trying to use the feature {{#each test in calculation}} in a template, but am getting an error saying "No such function: test". Here is a link to my code and I was hoping someone could show me where my mistake would be.
https://gist.github.com/claytonzaugg/c4191111159be68106f4
Thank you!
Clayton
You can either change your template helper to:
Template.ListCalculations.helpers({
test: function() {
return Calculations.find();
}
});
Or your html {{#each}} to:
{{#each calculations}}
<tr>
<td>{{test.testNumber}}</td>
<td>{{test.testName}}</td>
<td>{{test.inputOne}}</td>
<td>{{test.inputTwo}}</td>
<td>{{test.inputThree}}</td>
<td>{{#linkTo route="editCalculation"}}<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>{{/linkTo}}</td>
</tr>
{{/each}}
As #Michael Floyd mentioned, the in calculations is spurious.
Try editing the helpers to the following
Template.ListCalculations.helpers({
'test': function() {
return Calculations.find();
}
});
and the template binding to this in the each loop
{{#each test}}
<tr>
<td>{{testNumber}}</td>
<td>{{testName}}</td>
<td>{{inputOne}}</td>
<td>{{inputTwo}}</td>
<td>{{inputThree}}</td>
<td>{{#linkTo route="editCalculation"}}<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>{{/linkTo}}</td>
</tr>
{{/each}}

MeteorJS: Put date in dynamic template

WHAT I WANT TO BUILD IN DOM:
<table>
<tr> Today </tr>
<tr>
//data from Mongo
</tr>
...
<tr> Yesterday </tr>
....
//data from Mongo
..etc
</table>
CODE I HAVE :
<table>
{{#each posts}}
{{> postJobs}}
{{/each}}
</table>
<template name="postJobs">
<tr>
... // data from Mongo
</tr>
</template>
I think that it is necessary to compare the date from Mongo documents and today date or something like this.
Any idea how to build this ?
I guess you are requesting how to get the documents from collections grouped by date.
So on Top to see today chat, next block Yesterday, next block Previous Chats
Just call 3 times the same template
<template name="main">
<h1>Today</h1>
{{> list_posts posts=today}}
<h1>Yesterday</h1>
{{> list_posts posts=yesterday}}
<h1>Previous</h1>
{{> list_posts posts=previous}}
</template>
<template name="list_posts">
<table>
{{#each posts}}
<tr>
<td>{{col1}}</td>
<td>{{colX}}</td>
</tr>
{{/each}}
</table>
</template>
And then you need this helpers
Template.main.helpers({
today: function() {
return Posts.find() // col.date >= today
},
yesterday: function() {
return Posts.find() // col.date < today and >= yesterday
},
previous: function() {
return Posts.find() // col.date < yesterday
}
});
Good luck
Tom
I don't get what you exactly want to achieve. Comparing to today date would look like this, in an helper (that you can use in an {{#if compareDate}} statement:
compareDate: function(){
var today= new Date(new Date().getTime());
return this.date < today// it will get you true is the date field of your mongo document is older than today
}
Extra info, if you need yesterday:
var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));

How to do foreach in Meteor with Mongo?

Have collection
Peoples = new Mongo.Collection('peoples');
Peoples.insert({
name: ["Mark", "John", "Kate"]
});
I want to show all names in name
<template name="pTable">
<tr class="trJob">
<td>
{{#each names}}
{{> peopleName}}
{{/each}}
</td>
</tr>
</template>
<template name="peopleName">
<div>{{name}}</div>
</template>
What in my Temlate helpers
Template.pTable.helpers({
names: function(){
return Posts.tags;
}
});
Template.peopleName.helpers({
name: function(){
return Posts.tags.find();
}
});
I know that i have sh*** code in my Template helpers, any idea how to make it good ?
It must look like (in DOM)
<td>
<div>Mark</div>
<div>John</div>
<div>Kate</div>
</td>
simple array example
Template.home.helpers({
names: function(){
return [1,2,3];
}
});
<template name="home">
{{#each names}}
{{this}}
{{/each}}
</template>
will print:
1 2 3
each item becomes "this" inside the each loop. if you call another template within the loop, then its "this" will be populated by the item
Since you have different names for your collection, I will stick with the first one Peoples
Here is how I would proceed with your helpers:
Template.pTable.helpers({
names: function(){
return People.find({_id:yourId},{fields:{name:1}}).fetch();
}
});
And your peopleName template would be like this:
<template name="peopleName">
<div>{{this}}</div>
</template>
If you need to get all the names of all your documents, I need to nest your {{#each names}} into another {{#each doc}} where doc helper is like this (updated names as well) :
Template.pTable.helpers({
doc: function(){
return People.find().fetch();
},
names: function(){
return People.find({_id:this.id},{fields:{name:1}}).fetch();
});

Meteor RangeError: Maximum call stack size exceeded. on keypress event

Im trying to make a search box to filter down results of my returned collection in the client.
however when i actually try searching I'm getting the above error in the console.
RangeError: Maximum call stack size exceeded.
here is a look at my code.
<body>
{{#isolate}}
<header class="row-fluid">
{{> modules}}
</header>
{{/isolate}}
<div id="main" class="span11">
{{#if currentUser}}
{{#isolate}}
{{> customers_list}}
{{/isolate}}
{{#isolate}}
{{> contacts_list}}
{{/isolate}}
{{/if}}
</div>
</body>
my search form in inside the modules template
<template name="modules">
{{templateLogger "modules"}}
<ul id="module_list" class="nav">
{{#each list}}
<li>
{{name}}
</li>
{{/each}}
<form><input type="text" id="search"></form>
</ul>
and my customers_list template that I'm trying to filter the results
<template name="customers_list">
<table class="table">
<tr>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Phone</th>
</tr>
{{#each record}}
<tr>
<td>{{name}}</td>
<td>{{address}}</td>
<td>{{city}}</td>
<td>{{state}}</td>
<td>{{zip}}</td>
<td>{{phone}}</td>
</tr>
{{/each}}
</table>
</template>
and here is the event handler for the search form
Template.modules.events({
'keypress input#search': function (event) {
Session.set("currentFilter", $('input#search'));
}
});
and the form helper do display the results
Template.customers_list.record = function() {
qry = Session.get("currentFilter") || "";
if (qry != "") {
return Customers.find({$or: [ {'name': qry}, {'address': qry}, {'city': qry}, {'state': qry} ] });
} else {
return Customers.find({competitor: null}, {sort: {name: 1}});
};
}
I have no clue what the is causing this error from what i was able to read on other SO posts about the error it seems like its a infinite loop however those were not meteor specific questions and i don't know if that would make a difference? also if there is an infinite loop i cant find it.
any help would be grateful.
This error occurs when you pass large object as an argument to your method. For me for example the first Time I encountered this error, was when I passed a Meteor.Collection as an argument :s . I worked around that by passing the collection name as a String and then using eval() in the Methods to get the Collection on which proceed.
Conclusion: Always use strings, integers, small arrays or really small objects as arguments for methods called from your event handlers.
Changing this:
Template.modules.events({
'keypress input#search': function (event) {
Session.set("currentFilter", $('input#search'));
}
});
To This:
Template.modules.events({
'keyup input#search': function (event) {
Session.set("currentFilter", $('input#search').val());
}
});
I believe you just need the .val() on the jquery dom reference of the input field. Additionally I would recommend using keyup for the event for something like this.
For getting the results out like you want you likely want to use a regular expression. Here's what I'm using in my app.
Template.hudlies.found = function() {
var searchVal = Session.get("searchFilter");
if (searchVal != "") {
var searchResults = Hudlies.find({ name: { $regex: '^.*' + searchVal + '.*', $options: 'i' } });
};
return searchResults;
};

Dynamically insert template into table row

I have a table with data coming from a collection. When user clicks on a row I want to replace the content of the row with a form to edit the content. What would be the meteor way to do it without jQuery, if possible?
<template name="table">
<table>
{{#each items}}
{{> showrow}}
{{else}}
</table>
</template>
<template name="showrow">
<tr>
<td>{{name}}</td>
</tr>
</template>
<template name="editrow">
<tr>
<form>
… form html …
</form>
</tr>
</template>
Essentially, it's about replacing the showrowtemplate witn the editrow for onw row, I think. Is that a reasonable approach? Any pointers?
You could use a logical helper
<template name="table">
<table>
{{#each items}}
{{#if editmode}}
{{>editrow}}
{{else}}
{{> showrow}}
{{/if}}
{{/each}}
</table>
</template>
Then in your template helper
Template.table.editrow = function() {
return (this.editmode)
}
this lets you access the data context that would be in the collection for that particular item in the loop. So if you had a editmode:true for that item it would use the edit row instead.
Ok, that was easier than expected. 1:0 for Meteor:
I used the MongoDB _id as identifier of each row, in a data attribute: data-id="{{_id}}".
Then I set up a click event handler on <tr>-elements:
Template.booking.events({
'click tr': function(event, template) {
Session.set(editBookingId, event.currentTarget.getAttribute('data-id'));
}
});
A template helper listens to incoming ids and returns true if the ids match:
Template.booking.helpers({
'isEdited': function(id) {
return Session.get(editBookingId) == id;
}
});
In the template, I decide with {{#if}} whether to display the normal row or an edit dialog:
{{#if isEdited _id}}EDIT{{/if}}
Very little code. Very nice. Thanks for the pointers.

Resources