update handlebars template with new data in node+express - node.js

I've managed to get my handlebars working in a node+express app and loading in data from tweets based on a hashtag which I'm retrieving no problems and rendering the tweets on the page the first time no problem.
The issue I have now is trying to update the template with new tweets that come in.
I have in my routes the following code:
new twitter.TwitterStream().getHashTagStream(tweetsRetrieved);
function tweetsRetrieved(tweets) {
twitterSearchResults = tweets;
}
module.exports = function(app) {
app.get('/', function (req, res){
res.render('index', twitterSearchResults);
});
};
I've tried setIntervals around the rendering and getTweets method and when console logging I do see my response from Twitter with the latest tweets but the template isn't updating.
Any help would be greatly appreciated.
Thanks
Tom

Related

Send PDF as response to client

I'm facing a strange behaviour with PdfKit. I'm using Nodejs and Express. When I call my route that generate the PDF, the route itself is called twice, and I don't understand why.
Below is the smallest code that recreate this:
var express = require('express'),
app = express();
app.get('/', function (req, res) {
console.log('Route called with referer', req.headers.referer);
var PdfDocument = require('pdfkit'),
doc = new PdfDocument();
doc.pipe(res);
doc.addPage();
doc.end();
});
app.listen(7373, function () {
console.log('started');
});
In the terminal, I have these logs, refreshing only one time the page from the browser:
node tmp/server.js
started
Route called with referer undefined
Route called with referer http://127.0.0.1:7373/
Anyone knows why the route is called one more time automatically?
Ok, after some analysis, I found that it's the browser's PDF viewer that launch a second call. When using wget or curl, I see only one call and one log. So just be aware that code is parsed twice when diplaying the page from the browser.

NodeJS exports not defined in external JS file

I am calling a function from an external JS file in my routes file. So, I am trying to export a function from my externalFile.js file. However, when I run the node server, it throws Uncaught ReferenceError: exports is not defined . externalFile.js is in public/javascripts/ and the route files is in routes/.
External file (externalFile.js):
exports.capsolvingComplete = function (stdout){
//Received, display text and hide the spinner, put check in place.
$('#capsolv-complete').css("display", "block")
$('#capsolv-output').text(stdout);
}
Route file:
var express = require('express');
var router = express.Router();
var script = require('../public/javascripts/externalFile.js')
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'CapSolv' });
});
router.post('/file-upload', function(req, res){
script.capsolvingComplete("HI");
res.end("success");
})
module.exports = router;
Thank you for your help! Bit of a node noob here.
Looking at your example, mscdex is right. Anything you require in Node is designed to run on the server, and doesn't have access to the browser's DOM.
I would recommend building a REST API that accepts the file upload, stores it, and returns a JSON object containing metadata: i.e. where the file was stored, size, etc., and let your client deal with that.

Deleting posted content using $resource in AngularJS

I am new to AngularJS and am trying out a few things with posting and deleting content using $resource. I've got the posting working fine, but when I try to delete something that I've posted I get a 404 error.
DELETE http://localhost:3000/tasks?__v=0&_id=53c5ddcf2978af0000ccdc50&beginningDat…vacy=true&title=This+is+a+complete+task&website=http:%2F%2Fwww.hotmail.com 404 (Not Found)
I've been working on this for a few days now and I'm just not seeing what i am missing. I am using a MEAN stack. I've got mongoose, express, bodyParser, and cors as dependencies in my app.js and created my endpoints:
app.get('/tasks', api.getTask);
app.post('/tasks', api.postTask);
app.delete('/tasks/:_id', api.deleteTask);
Here is the code from my api.js which
exports.deleteTask = function(req, res){
var _id = req.params._id;
Task.remove({_id:_id}, function(err, task){
res.send(task + ' removed task successfully');
if(err){
res.send('Hey guys...he is still here.');
}
});
};
Here is my factory/service:
'use strict';
angular.module('achievementApp').factory('tasks', function($resource){
return $resource('http://localhost:3000/tasks/',{_id: '#_id'},{
get: {method:'GET', isArray: true},
add: {method:'POST'},
delete: {method: 'DELETE'}
});
});
And here is the code from the Ctrl:
$scope.taskList = tasks.get({});
$scope.removeTask = function(obj){
tasks.delete(obj);
var index = $scope.taskList.indexOf(obj);
console.log(index);
$scope.taskList.splice(index,1);
console.log('removeTask was called');
};
Any guidance on this would be greatly appreciated. I've tried just about everything I can to get it to work and have had no luck so far.
It looks like you have a mismatch between the angular code which is putting the _id in the query string and the express code which is looking for it as a route param, which looks in the path part of the URL. req.params comes from the path part before the ?. req.query comes from the query string part after the ?. It would be more conventional to use the path in terms of REST, so I suggest changing your angularjs code to have /tasks/:_id as the resource route.
Aside: Best to use relative paths in your browser JS and omit the protocol, host, and port. Otherwise your app won't work when you deploy it on the real web.

flexible query method/function for MongoDB + Express using NodeJs

I am working on an API with MongoDB+Express+Node.js. So far so good, I can query for one record by ID, I can query for a specific field, delete, add, etc.
I am looking for a method that can be called to create a generic query for mongoDB, where i will pass it a json representation of the model with 'some' data to search for. If the field is not specified in the json object, then it will only search on those fields specified.
Here is the boilerplate code I had, done, but I am very new to JavaScript and Node, and I think i need to parse or sanitize the query object before running the .find method.
Basically I want to be able to perform a query similar to how it is done in parse.com where you send an object model with the data you want to search for and you get all the results that match.
Any help would be greatly appreciated!
--This code is in my custom module--
exports.findByQuery = function(req, res) {
var query = req.query;
db.collection('artists', function(err, collection) {
collection.find(query).toArray(function(err, docs) {
res.send(docs);
});
});
};
--This is the routes file--
var express = require('express'),
artist = require('./routes/artists');
var app = express();
app.configure(function () {
app.use(express.logger('dev')); /* 'default', 'short', 'tiny', 'dev' */
app.use(express.bodyParser());
});
app.get('/search/', artist.findByQuery);
app.get('/artist/:id', artist.findById);
app.post('/artist', artist.addArtist);
app.put('/artist/:id', artist.updateArtist);
app.delete('/artist/:id', artist.deleteArtist);
app.listen(3000);
I just found that the code above DOES work, however you cannot search for _id for some reason.. But any other field would work. Still looking how to incorporate _id in the search.

How can I bootstrap models from express js into backbone at page load?

I have some data in a mongodb database and want to pass it to a backbone collection when I load the home page. One way of doing this would be to set up a node route like this:
exports.index = function(req, res){
db.users.find(function(err, docs) {
var docs_string = JSON.stringify(docs);
res.send(docs_string);
};
};
But this won't work because it won't render my jade template that pulls in the backbone code, it simply shows the JSON in plain text.
Alternatively, I could render my jade template passing in the data as a variable to jade:
exports.index = function(req, res){
db.users.find(function(err, docs) {
var docs_string = JSON.stringify(docs);
res.render('index', {
title: "Data",
docs_string: docs_string
})
});
};
Then in the jade template, have a script like this to add the users to my user collection:
script
var docs = !{docs_string};
var users = new app.Users();
_.each(docs, function(doc) {
var user = new app.User(doc);
users.add(user);
})
But this seems wrong, since I don't really want to pass the data to the jade template, I want to pass it to a backbone collection. Also, with this solution I don't know how to then include an underscore template (on the backbone side of things) into the page rendered by jade on the server side.
What is the standard way of passing data from a node server to a backbone collection?
Assuming your data is an object, you should convert it to string using JSON.stringify() and then insert in a page inside script tag, so your resulting HTML looks like this (I don't use Jade):
<script>
var data = {...}; // in template instead of {...} here should be the instruction to insert your json string
</script>
Then when the page loads, your script will be executed and the data will be available as a global variable in the browser so you can initialise backbone collection using it. This all is a good idea only to bootstrap your data on the first page load (to avoid extra request) and then use API to request data for this and other pages.
Check out Steamer, a tiny node / express module made for this exact purpose.
https://github.com/rotundasoftware/steamer

Resources