Setting the reactive data source from Route (Iron Router) is breaking reactivity - meteor

I have following code in the Router (Iron Router)
Router.map( function () {
this.route('hello',{path:'/hello',
onBeforeAction: function(){
console.log("QBConnected"+this.params.qbconnected);
Session.set("QBCONNECTED",this.params.qbconnected);
}
});
});
Following code in test.html
<template name="hello">
{{#if QBCONNECTED}}
<h1>Hello World if value={{QBCONNECTED}}</h1>
{{else}}
<h1>Hello World else value={{QBCONNECTED}}</h1>
{{/if}}
{{greeting}}
<input type="button" value="Click" />
</template>
Following code in test.js
if (Meteor.isClient) {
//Session.setDefault('QBCONNECTED',false);
Template.hello.greeting = function () {
return "Welcome to test.";
};
Template.hello.events({
'click input': function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
Template.hello.QBCONNECTED=function(){
console.log(Deps.active+"get QBCONNECTED called"+Session.get('QBCONNECTED'));
return Session.get('QBCONNECTED');
};
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
when I try to run this with the URL http://x.x.x.x:3000/hello?qbconnected=true
I see the string "Hello World if value=true" as expected
But when I try the url http://x.x.x.x:3000/hello?qbconnected=false, I see the string
Hello World if value=false. Can anyone please explain why it is entering the if block when the value of QBCONNECTED is false?
When I try to set the value manually from browser console by "Session.set("QBCONNECTED",true)" it prints "Hello World if value=true" as expected but when I try "Session.set("QBCONNECTED",false)" it prints "Hello World else value= " , can any one explain why QBCONNECTED is loosing it's value when set to false ?

This is happening because false from your querystring gets evaluated to the "false" string and not false boolean value as you might have expected.

Related

Meteor not adding and showing tasks in web page, it just blinks and malfunctions (To create Todos list to add and delete tasks)

//Client side code in client\main.js
Tasks=new Mongo.Collection('tasks');
Template.tasks.helpers({
tasks:function () {
return Tasks.find({},{sort:{createdAt:-1}});
}
});
Template.tasks.events({
"submit .add-task":function (event) {
var name = event.target.name.value;
Meteor.call('addTask',name);
event.target.name.value='';
return false;
},
"click .delete-task":function (event) {
if(confirm('Delete Task?')){
Meteor.call('deleteTask',this._id);
}
return false;
}
});
Meteor.methods({
addTask: function (name) {
if (!Meteor.userId()) {
throw new Meteor.Error('No Access!!');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: Meteor.userId()
});
},
deleteTask: function(taskId) {
Tasks.remove(taskId);
}
});
//Server side code in server\main.js
Tasks=new Mongo.Collection('tasks');
Meteor.methods({
addTask: function (name) {
if (!Meteor.userId()) {
throw new Meteor.Error('No Access!!');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: Meteor.userId()
});
},
deleteTask: function taskId() {
Tasks.remove(taskId);
}
});
//Html page
<head>
<title>tasklist</title>
</head>
<body>
{{> tasks}}
</body>
<template name="tasks">
{{> loginButtons}}
<h1>Add Task</h1>
{{#if currentUser}}
<form class="add-task">
<label>Task Name</label>
<input type="text" name="name" placeholder="Add Task" />
<input type="submit" value="Submit" />
</form>
{{else}}
<p>Please log in to add tasks</p>
{{/if}}
<hr />
<h3>Tasks</h3>
<ul>
{{#each tasks}}
<li>{{name}}{{#if currentUser}} X{{/if}} </li>
{{/each}}
</ul>
</template>
Please help, in this when i reload page it first add and and shows in the web-page and if i delete the try todelete the added then screen doesnot show even added tasks which are in MongoDB.
And when i do console, there is an empty array of added tasks
If it "blinks" this often means that your Method worked client side but not server side. The insert worked on your Minimongo (client) but not on the real MongoDB (server). So Meteor decide to rollback your insert on Minimongo.
You must have a problem inside your Method server side:
You can't use Meteor.userId() server side in your Methods, you have to use this.userId.
To avoid mistakes, only use this.userId inside the Meteor Methods client or server side.
// Server side
Meteor.methods({
addTask: function (name) {
if (!this.userId) {
throw new Meteor.Error('No Access!!');
}
Tasks.insert({
name: name,
createdAt: new Date(),
userId: this.userId
});
},
deleteTask: function taskId() {
Tasks.remove(taskId);
}
});
In Meteor, you don't have to duplicate your Methods client AND server side.
Methods should always be defined in common code loaded on the client and the server to enable Optimistic UI.
You just have to define your Methods and your collection one time inside a folder loaded on client and server. For exemple you can put your code inside a folder named both/.

Session.set vs changing the variable

I have this template:
<body>
{{> hello}}
</body>
<template name="hello">
{{greeting}}
</template>
And this is the controller:
if (Meteor.isClient) {
Template.hello.greeting = "Hi";
Meteor.setInterval(function() {
Session.set("greeting", Values.findOne({}).value.toString());
console.log(Values.findOne({}).value);
}, 1000);
}
On the console I'm getting the value in the collection Values. However, when I Session.set it to greeting, the variable isn't updated on the HTML page. The "Hi" I default it to just stays there while every second I get the value that should be in it on the console.
Try doing this:
Template.hello.greeting = function () {
return Session.get('greeting');
});

Have Meteor update a string every second

This is Meteor's default HTML:
<head>
<title>random-test</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<h1>Hello World!</h1>
{{greeting}}
<input type="button" value="Click" />
</template>
And this is Meteor's default Javascript code:
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to random-test.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
I changed the Javascript so I could have it update {{greeting}} every second:
if (Meteor.isClient) {
Template.hello.greeting = "hi";
Meteor.setInterval(function() {
Session.set("greeting", "hello");
console.log("Hi");
}, 1000);
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
It is console.logging "hi" every second. However, it is either not updating the value of greeting or Session.get isn't updating its value as it should (according to Meteor docs).
You need to return the Session.get('greeting') in a helper:
Template.hello.greeting = function() {
return Session.get('greeting');
}
Having Template.hello.greeting = "hi"; makes the template not dependent on Session.get('greeting'), so changes to that "session variable" won't cause any re-renderings. Or what do you expect to happen?

Passing data from server block to client block and also calling 3rd party package in Meteor

I am not able to pass data from server block to client block . I am also not sure the way I call self created package is right or wrong .
Here is my folder structure :
x/packages/me.js
x/packages/package.js
x/packages/smart.json
x/x.css
x/x.html
x/x.js
Here is all code :
me.js
Meteor.methods({
getTweets: function () {
var key = "my api key";
var response = Meteor.http.call( "POST", "http://localhost:8000/users.json",
{ params: { appkey: key ,uid: "example" }});
return response.content;
}
});
package.js
Package.describe({
summary: "summary etc"
});
Package.on_use(function (api){
api.use(["http"],["server"]);
api.add_files("me.js","server");
});
smart.json
{
"name": "name example",
"description": "desc",
"homepage":"as",
"author" : "xyz",
"version" : "0.1",
"packages": {}
}
x.html
<head>
<title>x</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<h1>Hello World!</h1>
{{greeting}}
<input type="button" value="Click" />
</template>
x.js
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to y.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
Meteor.call("hiren",function (err, data) {
console.log(data);
if(err) throw err;
});
}
});
}
if (Meteor.isServer) {
Meteor.call("getTweets",function (err, data) {
Meteor.methods({
"hiren":function(){
return data;
}
});
});
}
When I click the "click" button , it just shows undefined
One problem is here:
if (Meteor.isServer) {
Meteor.call("getTweets",function (err, data) {
Meteor.methods({
"hiren": function(){
return data;
},
});
});
}
You define your methods inside a callback function of getTweets method. This is probably not what you want to do, usually those are defined right in the server block as you want to have a predictable API. I cannot think of a reason to do such thing as you did, but even if there is one - you didn't call the getTweets function. So I guess it's a mistake.

Meteor, How can I display a url query in the client?

I am new to meteor, but it seems like this should be simple. I want to create a page that pulls a get variable down and displays it on the client
ex: www.example.com?yourname=bob
and the page would display
bob
I feel like this should be easy, but so far have not been able to do it. I created an call when the client loads that asks for the info, but it doesn't work on the first load for some reason. On subsequent loads it does.
<head>
<title>Page Chat</title>
</head>
<body>
<div id="wrapper">
{{> name}}
</div>
</body>
<template name="name">
{{name}}
<br />
<input type="button" value="Click" />
</template>
js code
if (Meteor.isClient) {
Meteor.startup(function(){
Meteor.call("getData", function(error, result){
if(error){
Session.set("name", "bob");
}
else{
Session.set("name", result.name);
}
});
});
Template.name.name = function(){
return Session.get("name");
};
Template.name.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
var connect = Npm.require('connect');
var app = __meteor_bootstrap__.app;
var post, get;
app
// parse the POST data
.use(connect.bodyParser())
// parse the GET data
.use(connect.query())
// intercept data and send continue
.use(function(req, res, next) {
post = req.body;
get = req.query;
return next();
});
Meteor.startup(function () {
});
Meteor.methods({
getData: function() {
return get;
},
postData: function(){
return post;
}
});
}
If possible I would like to share the data on the initial page load, it seems like a waste to create an separate page load to get information thats already there when the page is first loading.
It might be easier to use something like meteor-router. Then you could do
server side js:
Meteor.Router.add('/something', function() {
return this.params.yourname;
});
So if you visited example.com/something?yourname=Bob you would get back Bob.
Be careful when displaying something directly to the client from a querystring/input parameter as if you don't check it before it could be used for XSS.
Original url is "http://example.com:3000/test?xyz", you can use any one below
Router.current().request.url
"http://example.com:3000/test?xyz"
Router.current().url
"http://example.com:3000/test?xyz"
Router.current().originalUrl
"http://example.com:3000/test?xyz"
Router.current().route._path
"/test"
Router.current().route.getName()
"test"
https://github.com/iron-meteor/iron-router/issues/289

Resources