Meteor subscribe is not loading data from the server - meteor

I am having difficulties with meteor 1.6. First, I have created a database instance and tried to subscribe in the client. through form, I am able to input the data into my database. But could not retrieve it through the subscribe. can anybody tell me what wrong have I done in my code?
import { Template } from "meteor/templating";
import { Notes } from "../lib/collection";
import { Meteor } from "meteor/meteor";
// import { ReactiveDict } from 'meteor/reactive-dict';
import "./main.html";
/*
Template.body.onCreated(function bodyOnCreated() {
this.state = new ReactiveDict();
Meteor.subscribe("db1");
}); */
Template.Display.helpers({
notes() {
Meteor.subscribe("db1");
return Meteor.call('data');
}
});
Template.body.events({
"click .delete": function() {
Notes.remove(this._id);
},
"submit .formSubmit": function(event) {
event.preventDefault();
let target = event.target;
let name = target.name.value;
Meteor.call("inputs", name);
target.name.value = "";
return false;
},
"click .userDetail": function() {
if (confirm("Delete the user Detail ?")) {
Notes.remove(this._id);
}
}
});
here is the code for publication :
import { Mongo } from 'meteor/mongo';
export const Notes = new Mongo.Collection('notes');
Meteor.methods({
inputs:(name)=> {
if (!Meteor.user()) {
throw Meteor.Error("Logged in");
}
Notes.insert({
name: name,
createdAt: new Date()
});
},
data:()=>{
return Notes.find({});
}
});

Meteor.subscribe("notes"); should be in Template.body.onCreated lifycycle method. you need to write a
publish code seperately and not inside the Meteor.method. see below format,
Meteor.publish('notes', function tasksPublication() {
return Notes.find({});
});
Inside the helper just call the subscribed Collection a below,
Template.Display.helpers({
notes() {
return Notes.find({});
}
});
**NOTE: ** Never use Meteor.call inside the helper method. helpers are reactive and real time.

Related

Meteor.js Tracker.autorun / Tracker.depend on exported variable from server-side with set interval

I'm trying to get my head around Meteor's Tracker.autorun and Tracker.dependancy features.
I'm trying to do something that seems simple in my mind but I'm struggling to execute.
I have a server-side function, that I register as a method:
let count = 0
setInterval(()=>{
count ++
return count
}, 1000)
export default count
Register as a method:
import count from './setIntervarl'
Meteor.methods({
getData:function() {
return count
}
});
And then call up on the client side:
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Tracker } from 'meteor/tracker'
import './main.html';
// Setup reactive variable
rv1 = new ReactiveVar(9)
Meteor.call('getData', function(error, results) {
if(error){
console.log("error:"+error);
} else {
rv1.set(results)
}
});
// Display the output from reactiveVar
Template.someData.helpers({
someData: function() {
return rv1.get();
}
})
Can someone please show me how to use Tracker.autorun or Tracker.dependancy so that my UI updates with interval that is set in my server-side function
I'm having really trouble getting this working.
Many thanks
There will be no reactivity out of the box here. Meteor methods are not reactive but just a wrapped ddp call to a server (rpc-) endpoint that returns something.
In order to gain reactive data from the server, you need to subscribe to a publication. If you want only this counter being published, you may create a collection with a single document and publish it.
imports/CountCollection.js (both)
export const CountCollection = new Mongo.Collection('myCounter')
server/counter.js (server)
import { CountCollection } from '../imports/CountCollection'
let counterDocId
Meteor.startup(() => {
// optional: clear the collection on a new startup
// this is up to your use case
// CountCollection.remove({})
// create a new counter document
counterDocId = CountCollection.insert({ count: 0 })
// use the Meteor.setInterval method in order to
// keep the Meteor environment bound to the execution context
// then update the counter doc each second
Meteor.setInterval(function () {
CountCollection.update(counterDocId, { $inc: { count: 1 } })
}, 1000)
})
// Now we need a publication for the counter doc.
// You can use the `limit` projection to restrict this to a single document:
Meteor.publish('counterDoc', function () {
if (!counterDocId) this.ready()
return CountCollection.find({ _id: counterDocId }, { limit: 1 })
})
Now you can subscribe to this publication and get reactive updates to the document:
client/someData.js (client)
import { CountCollection } from '../imports/CountCollection'
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Tracker } from 'meteor/tracker'
import './main.html';
// Setup reactive variable
const reactiveCounter = new ReactiveVar(0)
const counterSubscription = Meteor.subscribe('counterDoc')
Template.someData.onCreated(() => {
const instance = this
instance.autorun(() => {
// counterSubscription.ready() will re-called
// when the publication released a new cursor
// which causes the autorun to re-run = reactivity
if (counterSubscription.ready()) {
// there is only 1 doc published, so no query require
const counterDoc = CountCollection.findOne()
reactiveCounter.set(counterDoc && counterDoc.count)
}
})
})
// Display the output from reactiveVar
Template.someData.helpers({
someData: function() {
return reactiveCounter.get()
}
})
Sidenote:
don't forget to get the paths and imports correct
Readings:
https://docs.mongodb.com/manual/reference/operator/update/inc/
https://docs.meteor.com/api/timers.html#Meteor-setInterval

Flowrouter Subscriptions

This is how my flowrouter looks like,
I tried all three options shown below: but unable to subscribe
import {CompanySettings} from '../imports/api/companysettingsMaster.js';
// And imported the api also..
FlowRouter.route('/', {
name: 'home',
subscriptions: function() {
// 1.
return this.register('companySettings', Meteor.subscribe('companySettings'));
// 2.
this.register('CompanySettings', Meteor.subscribe('companySettings'));
// 3.
return Meteor.subscribe('companySettings');
},
action: function() {
var themeSettings = CompanySettings.findOne({
"companyId": 101
});
if (themeSettings) {
console.log(themeSettings);
var scaleProcess = themeSettings.generalSettings.scaleProcess;
if (scaleProcess == 'retail')
BlazeLayout.render("retailMainLayout", {
content: "homepages"
});
else {
BlazeLayout.render("WSEmainLayout", {
content: "homepages"
});
}
} else {
console.log('no themeSettings');
}
}
});
But, not getting document at the end .. Any suggestions.. Thanks in advance
I got the answer for subscription in flowrouter which is as follows:
FlowRouter.route('/', {
waitOn: function () {
return Meteor.subscribe('companySettings');
},
});
Here companySettings is a name of collection in mongodb

How can i save the value in database with meteor?

In meteor framework inside pre-added code, the counter increases every time when it gets clicked. How to save the value using mongodb ?
Create a collection on the server side to persist the data:
Meteor.isServer {
Counter= new Mongo.Collection('Counter');
// Server side method to be called from client
Meteor.methods({
'updateCounter': function (id) {
if(typeof id && id) {
return Counter.update({_id: id}, {$set: {counter: {$inc: 1}}});
} else {
return Counter.insert({counter: 1})
}
}
})
// Publication
Meteor.publish("counter", function () {
Counter.find();
})
}
You can subscribe the data at the client:
Meteor.isClient{
Template.yourTemplateName.created = function () {
Meteor.subscribe('counter');
}
Template.yourTemplateName.heplers( function () {
counter: function () {
return Counter.findOne();
}
})
Template.yourTemplateName.event( function () {
'click #counterButtonIdName': function () {
if(Counter.findOne()) {
Meteor.call('updateCounter', Counter.findOne()._id);
} else {
Meteor.call('updateCounter', null);
}
}
})
}
Html sample
<template name="yourTemplateName">
<span>{{counter}}</span> //area where count is written
</template>
By this way you can achieve a secure server side processing of your data and the count will be persistent until you have data in the database. Also, this way you can learn Meteor's basics.
Just insert it to a collection. Here's an upsert (i.e., update if exists, insert if not) function:
if (Saves.find({_id: Meteor.userId()})){
Saves.update( {_id: Meteor.userId()}, {save: save} )
console.log("Updated saves")
}
else {
Saves.insert(save)
}
If the autopublish package exists, you can simply create a Mongo.Collection and insert this counter into the database:
var myCounter = 5;
var collection = new Mongo.Collection('collection');
collection.insert({counter: myCounter});
Hope this helps.

How do I dynamically publish collections via a Meteor method?

I dynamically create collections with this method:
createPlist: function(jid) {
try {
Plist[jid] = new Meteor.Collection(pid);
} catch(e) {
console.log("oops, I did it again");
}
Plist[jid].insert({
...,
...,
public:true,
uid:this.userId
});
}
Then I am wanting to publish these selectively, and I am attempting to do it via a method:
getPlist: function(jid,pid) {
// var future = new Future();
try {
Plist[jid] = new Meteor.Collection(pid);
} catch(e) {
console.log("oops, I did it again");
}
Meteor.publish(pid, function() {
console.log(Plist[jid].find({}));
// future["return"](Plist[jid].find({}));
return Plist[jid].find();
});
// return future.wait();
},
This returns 'undefined' to my Template helper, and returns nothing (i.e. waits forever) using Future.
Any user can log in and create a Plist collection, which can be either public or not. A user can also subscribe to any collection where public is true. The variable jid is passed to the method 'getPlist' from the template. It is stored in the user's Session.
Thanks! I hope I have explained it well enough!
And of course the template:
Template.plist.helpers({
getPlist: function() {
Pl = []
jid = Session.get('jid');
//alert(jid);
pid = "pl_"+jid;
// console.log(pid);
Meteor.call('getPlist', jid, pid, function(err,res) {
console.log(res); //returns undefined
try {
Pl[jid] = new Meteor.Collection(pid);
} catch(e) {
console.log(e);
}
Meteor.subscribe(pid);
// return Pl[jid].find({}).fetch();
});
}

Meteor - insert failed: Method not found

I have a problem with my Meteor's JS file. I get this error "insert failed: Method not found" when I try to insert any data to the database and reflect on chart. I've tried fetching data directly from db that didn't work too...
thanx in advance.
LinePeople = new Mongo.Collection("LinePeople");
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
if (Meteor.isClient) {
console.log("in LIne Client");
//LinePeople = new Mongo.Collection(null);
Template.linenvd3.rendered = function() {
var chart = nv.models.lineChart()
.margin({left: 80}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(true) //Show the y-axis
.showXAxis(true) //Show the x-axis
;
nv.addGraph(function() {
chart.xAxis.axisLabel('Person number').tickFormat(d3.format('d'));
chart.yAxis.axisLabel('Age (years)').tickFormat(d3.format('d'));
d3.select('#lineChart svg').datum(
[{ values: LinePeople.find().fetch(), key: 'Age' }]
).call(chart);
nv.utils.windowResize(function() { chart.update() });
return chart;
});
Deps.autorun(function () {
d3.select('#lineChart svg').datum(
[{ values: LinePeople.find().fetch(), key: 'Age' }]
).call(chart);
chart.update();
});
};
Template.linenvd3.events({
'click #addDataButton': function() {
console.log(" in line addButton");
var age = getRandomInt(13, 89);
var lastPerson = LinePeople.findOne({}, {fields:{x:1},sort:{x:-1},limit:1,reactive:false});
if (lastPerson) {
console.log(" in lastPerson.. if block");
LinePeople.insert({x:(lastPerson.x + 1), y:age});
} else {
console.log(" in lastPerson.. else block");
LinePeople.insert({x:1, y:age});
}
},
'click #removeDataButton': function() {
console.log(" in line removeButton");
var lastPerson = LinePeople.findOne({}, {fields:{x:1},sort:{x:-1},limit:1,reactive:false});
if (lastPerson) {
LinePeople.remove(lastPerson._id);
}
}
});
}
if (Meteor.isServer) {
console.log("in line Server");
}
While following the Getting Started tutorial on the official meteor.js website I've had the same problem with autopublish turned on.
Turned out the issue was I created my Tasks collection inside the imports/ folder. Thus it was not implicitly imported on the server.
I had to explicitly import it on the server to solve the issue.
server/main.js
import { Meteor } from 'meteor/meteor';
import '../imports/api/tasks.js';
Meteor.startup(() => {
// code to run on server at startup
});
As you can see the import is not used by my code but is required anyways.
Thanks for the help... I actually got it worked by publishing the collection and giving it some permissions:
This code is placed in "myapp/shared/collections.js". (Placed them separately to handle all the other collections which I would add for other graphs)
lineVar = new Meteor.Collection("linenvd3");
lineVar.allow({
insert: function () {
return true;
},
update: function () {
return true;
},
remove: function () {
return true;
}
});
This code is placed in "myapp/server/publish.js"
Meteor.publish('line', function () {
return lineVar.find();
});
Then, this is modified Javascript made look more simpler and comprehensive.
if (Meteor.isClient) {
Meteor.subscribe('line');
Template.linenvd3.rendered = function() {
var chart = nv.models.lineChart()
.margin({left: 80})
.useInteractiveGuideline(true)
.transitionDuration(350)
.showLegend(true)
.showYAxis(true) //Show the y-axis
.showXAxis(true) //Show the x-axis
;
nv.addGraph(function() {
chart.xAxis.axisLabel('Person number').tickFormat(d3.format('d'));
chart.yAxis.axisLabel('Age (years)').tickFormat(d3.format('d'));
d3.select('#lineChart svg').datum(
[{ values: lineVar.find().fetch(), key: 'Age' }]
).call(chart);
nv.utils.windowResize(function() { chart.update() });
return chart;
});
Deps.autorun(function () {
d3.select('#lineChart svg').datum(
[{ values: lineVar.find().fetch(), key: 'Age' }]).call(chart);
chart.update();
});
};
}

Resources