Meteor not displaying data from collection in html - meteor

I am trying to get data from a collection in meteor and using a helper passing it to a template.
Here is my code in collection:
Meteor.publish('displayCustomers', function tasksPublication() {
return Customers.find();
});
Below code in template JS file
Template.customerlist.onCreated(function() {
Meteor.subscribe('displayCustomers');
});
Template.customerlist.helpers({
displayCustomers :function(){
console.log(Customers.find({}));
return Customers.find({});
},
});
Template:
<template name="customerlist">
<h1>All registered users</h1>
{{#each displayCustomers}}
{{fname}}
{{/each}}
</template>
It is only displaying HTML content i.e. <h1>All registered users</h1>

Check that your publication is returning values to the client with this MiniMongo chrome extension

Check to make sure Customers is defined on the server and that your publish block is running only on the server.
Also I would toss a debugger into your onCreated block to make sure that your subscribe is being initialized.
Other than that, your code looks fine. I would try installing MeteorToys Mongol for client pub/sub debugging. https://atmospherejs.com/msavin/mongol

You need to actually fetch documents in your template :
Template.customerlist.helpers({
displayCustomers :function(){
return Customers.find().fetch(); //will return an array with all published documents
},
});

Related

How to access the subscriptions inside the HTML file?

Usually when I use helpers, I can access the returned values as below:
Template.oveview.helpers({
item: function () {
return Requests.find({});
},
Then in the client side I can use {{#each item}}, But I don't know how to display them in the .html when using publish and subscribe
Here is my publish:
Meteor.startup(() => {
Meteor.publish('requests', function queryRequests() {
return Requests.find({});
});
});
And here is my subscribe:
Template.overview.onCreated(function() {
Meteor.subscibe('requests');
});
How can I display the returned value from publish in the client side?
You can use it in a few different ways. You can use Meteor templates to insert a HTML snippet for every item in-between existing HTML:
{{#each item}}
{{> htmlTemplateName}}
{{/each}}
Or you can just place raw HTML in the {{#each}} loop:
{{#each item}}
<p>{{propertyX}}</p>
<p>{{propertyY}}</p>
{{/each}}
You might run into problems with the pubsub, depending on load order (I don't know load orders, I'm afraid). I used the iron-router package in my project, to bind certain end-points to specific HTML files. iron-router has this nice parameter you can set for every page, called waitOn, where I placed my subscriptions. This means that subscribing to a certain collection happens before anything else.
Router.configure({
layoutTemplate: '_layoutTemplate',
name: 'myTemplateName',
waitOn: function() {
return [
Meteor.subscribe('requests'),
//Add other subscriptions here
];
}
});

Meteor JS and State (address) select element

I want to have a state select in meteorjs for an address input field. I feel like listing out all the states in a massive html string of <option>s is wrong. Is there a documentation or preferred way to do this?
In frameworks like CakePHP, I would create a DB table related to address and just use the form helper methods to output the markup based on the table.
If you'd prefer to fetch a set of states from a database, you could create a Meteor Collection to store them.
States = new Mongo.Collection("states");
If you've removed the autopublish package (which if you haven't, you should), you need to then publish this collection,
if (Meteor.isServer) {
Meteor.publish("states", function() {
return States.find();
}
}
and then subscribe to it, and make it available to your template with a helper:
if (Meteor.isClient) {
Meteor.subscribe("states");
Template.myForm.helpers({
states: function() {
return States.find();
}
});
}
Then you can output the collection in your template as such:
<select>
{{#each states}}
<option>{{name}}</option>
{{/each}}
</select>
A nice way to enter the data into the database is through the Meteor Mongo shell or through a GUI like RoboMongo

Meteor template gets rendered twice

My template is getting rendered twice on first load. I notice this because in
Template.home.rendered = function() {
console.log('rendered'); // => this is printed out twice
console.log(Data.find({}).count()); // => this is initially 0, then 1 the second time
}
Furthermore, on the first load, no Data is available. Yet on the second load, the Data is there.
Does anyone know what this problem might be, and why the data only appears the second time?
You need to find a way to render the template when your data is available.
Using this template structure, the if block content, which happens to be the template displaying your data, will be rendered only when the myDataIsReady helper returns true. (thus triggering the rendered callback only once, with data immediately available).
<template name="displayData">
<p>This is my data : {{this}}</p>
</template>
<template name="home">
{{#if myDataIsReady}}
{{#each data}}
{{> displayData}}
{{/each}}
{{/if}}
</template>
You have to define a subscription handle (an object returned by Meteor.subscribe) in order to use it's reactive ready method : we'll reference it in the myDataIsReady helper to track data availability, and the helper will automatically rerun when the state of ready changes.
Meteor.startup(function(){
// this subscription should return your data subset
myDataHandle=Meteor.subscribe("myData");
});
Template.home.myDataIsReady=function(){
return myDataHandle.ready();
}
Template.home.data=function(){
return Data.find({});
}
But that's quite annoying for such a simple task.
That's why I suggest using the Iron Router which makes things way simpler !
Add it to your project using "mrt add iron-router", then in a client/router.js and client/router.html, use this boilerplate code :
Router.configure({
loadingTemplate:"loading"
});
Router.map(function(){
this.route("home",{
path:"/",
// we indicate which subscription has to be marked ready in order to load the template
waitOn:function(){
return Meteor.subscribe("myData");
}
// the result of this function will become our target template data context
data:function(){
return Data.find({});
}
});
});
<template name="home">
{{#each this}}
{{> displayData}}
{{/each}}
</template>
<template name="loading">
<p>Data isn't ready yet...</p>
</template>
As you can see, the Iron Router allows us to specify simply what we painfully achieved manually in the first code example (waiting on a particular subscription to render a template), and of course we get free routing, loading mechanisme, layout management, etc...
Search the web for a complete iron-router tutorial (my code is untested, but I hope it is ok and should get you started), it's so awesome that it's gonna be merged to Meteor ultimately.
I had a body.html in /client and a appBody.html in /client/templates, with, in iron router:
Router.configure({
layoutTemplate: 'appBody',
});
Both body templates were rendered (and happened to be the same). Obviously, the body.html in /client needed to be removed.

Setting {reactive: false} when searching a collection in Meteor still updates the template

I've got a news feed idea I'm trying out in Meteor, but I'm having issues with making the damn thing behave :) I want it to load up the news feed on page load / refresh, but not when the data changes. I found in the documentation that adding {reactive: false} to the find method of a collection should make it stick to the results generated on render, but it doesn't seem to work for me. Meteor keeps updating the template right away.
Here's the code I've got:
On the server side:
Meteor.publish("newsfeed", function () {
return Newsfeed.find({});
});
On the client side:
Meteor.subscribe('newsfeed');
Template.feed.feed_data = function() {
var feed = Newsfeed.find({}, {
sort: {updated_time: -1},
limit: 10,
reactive: false
});
return feed;
};
In the template:
<template name="feed">
<div id="feed-wrapper">
<ul>
{{#each feed_data}}
<li>
<div class="message">{{message}}</div>
</li>
{{/each}}
</ul>
</div>
</template>
If I then run Newsfeed.update({_id: 'some_random_id'}, {$set: {date_created: 'some_random_date'}}) in Dev Tools, the template updates the sorting of my news feed and changes it.
How do I make it not do that? :D
This is arguably a bug in Meteor. Passing reactive: false means that minimongo itself doesn't set up some code to say "observe and if it changes, invalidate". But #each has its own separate observeChanges call which uses the observe callbacks directly (not a reactive "invalidate and recalculate") to update the list. Probably we should not do this if the cursor has reactive: false on it. Track this in https://github.com/meteor/meteor/issues/771 !
Thats a bit odd, it ought to work. You could also use preserve:
Try adding this line in your client js
Template.feed.preserve(['#feed-wrapper']);
Btw is the template name="feed" in another template? Does this template have any reactive variables in it?

Client-side-only reactivity with Meteor?

I have a collection published on the server and auto-subscribed on the client. I'd like to set the 'selected' item on the session and have the template update to display only the selected item, but it seems this can only be done with a roundtrip to the server (which is totally unnecessary).
Common:
var Missions = new Meteor.Collection('missions');
Client:
Template.missionList.missions = function() {
var currMission = Session.get('selectedMission');
var searchMission = {};
if(currMission)
{
searchMission['_id'] = currMission;
}
return Missions.find(searchMission);
};
Template.missionList.events({
'click div.mission': function (e, t) {
Session.set('selectedMission',
this._id == Session.get('selectedMission') ? null : this._id
);
}
});
Template.mission.isSelected = function() {
return this._id == Session.get('selectedMission');
};
Meteor.autosubscribe(function () {
Meteor.subscribe("missions");
});
Server:
Meteor.publish('missions', function() {
// there are really some filters here, but removed for simplicity
return Missions.find();
});
Template:
<template name="missionList">
<div class="missionList">
{{#each missions}}
{{> mission}}
{{/each}}
</div>
</template>
<template name="mission">
<div class="mission{{#if isSelected}} selected{{/if}}">details</div>
</template>
My requirement is for the Missions.find() in Template.missionList.missions to filter the client-side cached results, rather than to re-request from the server, but I can't seem to find a flag or settings to allow me to tell minimongo to only use the currently available data.
I'm also not entirely sure if this is what I should be doing, I started out just using jQuery to hide the non-selected missions but getting my head round Meteor and it seems a natural fit to use the data and reactivity to drive selection/local-filtering.
Is there any way the roundtrip can be avoided or am I just using it wrong?
By setting up a publish / subscribe relationship, you are creating a simplified form of database replication. Minimongo will have a copy of the data locally and execute the find() locally without a server roundtrip. If you are seeing network activity or calls to the server code, it is because meteor is regularly working behind the scenes to keep the subscription in sync with the server, not for your specific find.
This also means you have to wary of sending too much data to the client, so your server side publish function may want to filter by the specific fields needed by client, in addition to existing your selection criteria.

Resources