i am very new to nodejs and meteor. i need to create a page content-type application/json and data from mongo collection. So when collection data change json page must be change.
For json page i use this example:
https://stackoverflow.com/a/23666992/1446182
if (Meteor.isServer) {
Meteor.startup(function () {
try{
var interval = Meteor.setInterval(function() {
var result = Meteor.http.call("GET", "http://192.168.2.144//ihale/meteorGetPage" );
var resultJson = JSON.parse(result.content);
var json = IhaleCollection.findOne();
IhaleCollection.update(json, {$set: {json: resultJson}});
}, 1000);
}
catch(err) {
console.log(err);
}
});
Router.map(function() {
this.route('jsonExample', {
where: 'server',
path: '/json',
action: function() {
var obj = IhaleCollection.findOne();
var headers = {'Content-type': 'application/json'};
this.response.writeHead(200, headers);
this.response.end(JSON.stringify(obj));
}
});
});
}
When Meteor.startup i start to update IhaleCollection every second.
So how i can update json page when IhaleCollection change?
You can't. Not this way anyway. JSON has no builtin mechanism to detect if the source has changed and given that the router endpoint is outputting raw JSON data with no javascript, no automatic updates will happen. Only when a client refreshes the endpoint will there be an update.
Meteor deals with reactive data by inserting javascript in the underlying html page. If you want to utilize that then you have to write a template, write a helper method to return JSON and use the helper method in the body.
The helper method should look something like this:
Template.jsondoc.helpers{(
json: function(){
return JSON.stringify(IhaleCollection.findOne());
}
})
Template can be as simple as that:
<template name="jsondoc">
{{json}}
</template>
and your route will be as simple as this:
Router.route('/jsondoc');
Related
I am building a chat and based on the chatroom selected by the currentUser, I want to publish messages with this function:
Meteor.publish('messages',function(){
return Messages.find(
{chatId: 'QMMjBgCvLcnLvJPvx'},
sort:{timestamp: -1}
});
});
Now the chatId is still hardcoded, but it needs to be dynamic. The chatId is passed in the URL(e.g..../chat/QMMjBgCvLcnLvJPvx). In the client based code I have used to read the chatId:
var chatId = Router.current().params._id;
Iron Router
But this doesn't work server side. Is there a way to send the chatId from the URL to the server so I use Meteor.publish as mentioned above. Any help appreciated :)
Pass in the variable when you subscribe I.e.
Meteor.subscribe("messages", {chatId: Session.get("current-room")})
In the publication:
Meteor.publish('messages',function(chatId){
return Messages.find(
{chatId: chatId},
sort:{timestamp: -1}
});
});
In your route, you can subscribe to a publication and pass a param inside waitOn which will cause the app to show your loading template until the subscription is ready and the chatId will be reactive.
Configure loading template:
Router.configure({
layoutTemplate:'templateName',
loadingTemplate: 'anotherTemplateName'
});
Your route:
Router.route('/chat/:_id',{
waitOn: function(){
return Meteor.subscribe('messages', this.params._id);
},
action: function(){
//render your template with data
this.render('templateName', {
data: function () {
//will return object to the template which you can use in both HTML and JS. Also necessary for the link.
return Somethings.findOne({_id: this.params._id})
}
})
}
});
Publication:
Meteor.publish("messages", function (chatId) {
//the chatId comes from our subscribe in our route
return Messages.find({chatId: chatId});
});
Thanks for your answers and the hints. After some more modifications I arrived at this, which solved the issue:
var chatId = Router.current().params._id
this.wait(Meteor.subscribe('messages', chatId));
I am trying to store email messages as JSON (as parsed by Mailgun) in a Mongo.Collection through a Mailgun webhook. I set up an iron-router server-side route to handle the request, but this.request.body is empty. I am using Mailgun's "Send A Sample POST" to send the request, and the POST looks fine using e.g. http://requestb.in/. I was hoping that request.body would have the data, as mentioned in How do I access HTTP POST data from meteor?. What am I doing wrong?
Router.map(function () {
this.route('insertMessage', {
where: 'server',
path: '/api/insert/message',
action: function() {
var req = this.request;
var res = this.response;
console.log(req.body);
...
I'm not sure that is the right syntax. Have you tried using Router.route ?
Router.route('insertMessage',
function () {
// NodeJS request object
var request = this.request;
// NodeJS response object
var response = this.response;
console.log("========= request: =============");
console.log(request);
// EDIT: also check out this.params object
console.log("========= this.params: =============");
console.log(this.params);
// EDIT 2: close the response. oops.
return response.end();
},
{
where: 'server',
path: '/api/insert/message'
}
);
I think the issue is that Mailgun sends a multipart POST request, e.g. it sends "fields" as well as "files" (i.e. attachments) and iron-router does not set up a body parser for multipart requests. This issue is discussed here and here on iron-router's Github Issues. I found this comment particularly helpful, and now I can parse Mailgun's sample POST properly.
To get this working, in a new Meteor project, I did
$ meteor add iron:router
$ meteor add meteorhacks:npm
In a root-level packages.json I have
{
"busboy": "0.2.9"
}
which, using the meteorhacks:npm package, makes the "busboy" npm package available for use on the server via Meteor.npmRequire.
Finally, in a server/rest-api.js I have
Router.route('/restful', {where: 'server'})
.post(function () {
var msg = this.request.body;
console.log(msg);
console.log(_.keys(msg));
this.response.end('post request\n');
});
var Busboy = Meteor.npmRequire("Busboy");
Router.onBeforeAction(function (req, res, next) {
if (req.method === "POST") {
var body = {}; // Store body fields and then pass them to request.
var busboy = new Busboy({ headers: req.headers });
busboy.on("field", function(fieldname, value) {
body[fieldname] = value;
});
busboy.on("finish", function () {
// Done parsing form
req.body = body;
next();
});
req.pipe(busboy);
}
});
In this way I can ignore files (i.e., I don't have a busboy.on("file" part) and have a this.request.body available in my routes that has all the POST fields as JSON.
Still trying to get my footing with Meteor. I need an AJAX like method to trigger something on the server and get a response back that it was done.
What I want to do is something like this:
Router.map(function() {
// Remove Blog Posting
this.route('blogRemove', {
path: '/blogRemove/:_id',
where: 'server',
handler: function() {
var request = this.request;
var response = this.response;
// Do some deleting here
}
});
});
This would trigger some server call to remove the blog with the given _id. I would then reply with JSON via the response object. But after 15yrs of development work I have learned: Just because it's possible, doesn't mean it's the right way...
So, the question is: For AJAX-type calls, is this the preferred way to do them in Meteor/Iron Router, or is there some more efficient/elegant way to do them?
Normally you would use a meteor method for that. For instance:
Server:
Meteor.methods({
blogRemove: function (id) {
// delete the blog
return {status: "OK", msg: "removed blog " + id};
}
});
Client:
Meteor.call('blogRemove', id, function(err, result) {
console.log(result);
});
I'm trying to access data passed from iron router in the javascript function
router.js
this.route('editOrganization', {
path: '/editOrganization',
waitOn: function() {
return [
Meteor.subscribe('organization', this.userId)
];
},
data: function() {
return Organizations.findOne();
}
});
now if I wanted to access a property of organization in html (editCompany.html) I can do the following
{{name}}
but how do I access that same property in the js file
Template.editOrganization.rendered = function() {
//how do I access name?
}
UPDATE:
so if I click a link to edit organization I can get the value via
this.data.name
However, if I reload the page (same url) it throws an error saying data is null.
It is accessible through the rendered function context.
Template.editOrganization.rendered = function() {
var name = this.data && this.data.name;
};
This is confusing for many people but you need to configure the router to actually wait for the subscriptions you returned with waitOn.
Router.onBeforeAction('loading')
You can read the author's explanation here:
https://github.com/EventedMind/iron-router/issues/554#issuecomment-39002306
I am trying to achieve a dynamic subscription of collection data based on the parameter in the url.
On Client side, I have the following subscription code in main.js file.
cSubscribe = Meteor.subscribe('cPublish', Session.get('param1'));
On Server, I have the following publish code in main.js file.
Test = new Meteor.Collection('test');
Meteor.publish('cPublish', function(param1) {
return Test.findOne({_id: param1});
});
In the router, I am setting the url parameter value in the Session, Session.set('param1', value); and when I try cSubscribe.ready(), it is returning false. Until the subscription is ready I am showing a loading template.
The route snippet,
'/test-url/:value': function(value) {
Session.set('param1', value);
if (cSubscribe.ready()) {
//some code
} else {
return 'loading';
}
}
What is wrong with the process ? Is there any better way of achieving dynamic subscription ?
First, I hope, you use iron-router (-:
In router, for example, in onBeforeAction() you have to set Session.set('param1', value);
Then on client try to use smth like this:
Meteor.startup(function() {
Deps.autorun(function() {
var param = Session.get("param1");
if(param) {
cSubscribe = Meteor.subscribe('cPublish', param);
});
});
In other words, you have to resubscribe after url changed.