I developed an Android app that save via http request some data in mongodb. everything is working fine and it's ok. Now it comes the second part of the project, to use this data in a html javascript, and I can't figure out how to do it.
This is from my server.js and it's the part where I get the data from database and I send it to localhost:3000 in res.send(data).
app.get('/',(req,res)=> {
MongoClient.connect(url, { useNewUrlParser: true }, function(err,
db) {
if (err) throw err;
var dbo = db.db("mydb");
dbo.collection("date_locatie").find({"imei" : imei_number},
function(err, result) {
if (err) throw err;
console.log(data.imei);
res.send(data);
});
});
});
Now I have made a html page called mapa.html and after I past data from mongo to node (res.send(data)) I've tried to send the html page too with res.sendFile(path.join(__dirname+'/mapa.html')) and it seems express/node.js not working like this. If I put the res.sendFile line after res.send I receive an error
Error: Can't set headers after they are sent.
I understand I can't res.sendFile after I res.send, but I can't figure out how I can use the data from mongodb in that html page.
You cannot pass variables to an html page. You must use a template engine. I recommend using EJS templates. You can install it by running npm install ejs, then inside your code specify the template engine that you are using by writing app.set('view engine', 'ejs');. The pages you create must have an extension .ejs. Now you can load the page using render, like this:
res.render('page name',{
variables: someVariable
});
And inside of your template print the passed variables with <%= variables %>
Hope my answer helps. If you have any questions feel free to ask.
Related
I'm just learning how to make a simple web-application for my dorm that would assign each participant a random number once they enter their name. There is a form field with one text box and a button. The text box (form) needs to send the full name (a single string) to the MySQL database so that later on I could retrieve the full list with the assigned numbers to actually use the application in the real world. Just for redundancy, I've put in code that creates a new database and a table every time, but then SQL ignores it if the DB and table already exist.
My fundamental problem is that I can not get data from my form in HTML. I'm using express.js and am trying to retrieve it, then post it into my database via the SQL module. Now as I'm a complete newbie, I have no idea how it should work. For the past 4 days, I've searched all over the internet to try to solve this issue. I don't know if the js document is the problem or the HTML document.
This is my HTML form (do tell me if you would need the whole thing):
<form action="/createPerson" method="POST">
<input type="text" name="name" value="Ime in priimek">
<input type="submit" name="name" value="Potrdi" class="gumbek">
</form>
And here is my complete node.js document:
var mysql = require('mysql');
var express = require("express");
var bodyParser = require("body-parser");
var urlencodedParser = bodyParser.urlencoded({
extended: false
});
const http = require('http');
var fs = require('fs');
const app = express();
const path = require('path');
const router = express.Router();
// Unique random number generator module
const uniqueRandom = require('unique-random');
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
server = http.createServer(app);
server.listen();
// Start connecting to MySQL database
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "root",
database: "mydb"
});
//if database mydb exists, ignore database creation
let createMydb = "CREATE DATABASE if not exists mydb"
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
con.query(createMydb, function(err, result) {
if (err) throw err, console.log("Database already exists!");
console.log("Database OK (Already exists, will not create new one)");
});
});
//if table person exists, ignore table creation
let createTable = "CREATE TABLE if not exists person (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), number VARCHAR(255))";
var sql = createTable;
con.query(sql, function(err, result) {
if (err) throw err, console.log("Table exists, will not create new table");
console.log("Table OK (Already exists, will not create new one)");
console.log('Running at Port 3000');
console.log("Connected. Commencing value input into database.");
//var post = { name: req.body.name, number: random }
//app.get('/createPerson', urlencodedParser, function(err, req, res) {
if (err) throw err;
//res(req.body.name)
});
router.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
//__dirname : It will resolve to your project folder.
});
/*const random = uniqueRandom(1, 100);
const values = ['/createPerson', String(random())];
var insert = "INSERT INTO person (name, number) VALUES (?)"
con.query(insert, [values], function(err, result) {
if (err) throw err;
console.log("Value was inserted into database.");
});*/
app.get('/createPerson', function(req, res) {
res.render('form'); // if jade
// You should use one of line depending on type of frontend you are with
res.sendFile(__dirname + '/index.html'); //if html file is root directory
});
app.post('/createPerson', urlencodedParser, function(req, res) {
const random = uniqueRandom(1, 100);
const values = [String(req.body.name), String(random())];
var insert = "INSERT INTO person (name, number) VALUES (?)"
console.log(req.body.name);
con.query(insert, [values], function(err, result) {
if (err) throw err;
console.log("Value was inserted into database.");
res.sendFile(__dirname + '/numberAssigned.html');
res.end();
});
});
Now every time I press the button in the form, I get Cannot POST /createPerson inside the browser and no data was sent to my database. Browser (network tab) also gives me 404. Maybe it can't find the form?
I am a complete newbie at all of this, I can manage HTML and CSS, Javascript is something really new to me. If you find the time to help me, THANK YOU FROM THE BOTTOM OF MY HEART!
The problem is that you are using node.js http module and express at the same time.
You are setting up /createPerson within the express.js app, but starting the node.js http server instead. So, no end-points are present in the server you've started - hence 404 Page Not Found.
Usually, you use just one of them. Node.js http module provides an ability to start a low-level HTTP server. Express, on the other hand, is a more high-level solution for building http services. So in your case, I would stick with express and throw out http (express is using http module under the hood anyways).
But the fundamental problem of your solution is that it is too big and complex to bootstrap from scratch.
It could be really confusing to figure out what is going on in a complex app, since you are trying to do many things at once - express http server + sql database + html forms... Many things can go wrong, so better try a "Hello World" approach instead.
To debug a problem like that, I would downscale the app and try to check every little interaction level by level:
Level 1
Comment out http module usage and every mapping in express except POST for /createPerson
Make sure you run express app.listen() after the end-point setup.
Comment out all database access in /createPerson handler and leave just a log statement like that:
app.post('/createPerson', urlencodedParser, function(req, res) {
console.log(req.body.name);
}
Now run your script with node.js and try to check the POST on /createPerson with curl:
curl --data-urlencode "name=John Doe (Junior)" http://localhost:3000
(make sure you are using the right port)
Check node.js logs - you have to see a name you're sending with curl in there.
When you see the name in logs, Level 1 is complete!
Level 2
Now try to do the same POST, but form an HTML form.
Add a static mapping on /public to node.js.
Run the node.js server.
Open a page with the HTML form and POST it.
Make sure your form is sending data to correct URL and you see the data in node.js logs
Level 3
Only now, when you have data flowing from html to node.js, you can try to extend the system with a database. Reintegrate db access code back into /createPerson and debug the solution.
Good luck with the next levels!
I want to send an application/javascript response from my Express server, passing the data which I have got from MongoDB.
This is a response to a call for loading some in a third party website.
I have created all the different parts of the process, now just need to pass on the data into the Javascript response.
server.js
app.get('/', (req, res) => {
productInfo(param1, param2, res)
}
productInfo.js - MongoDB call
function productInfo(param1, param2, res){
Product.find({key1: param1}, (err, docs) => {
let idList = docs.idList;
res.set('Content-Type', 'application/javascript');
res.sendFile(__dirname + '/script.js', (err) => {
if (err) { console.log(err) }
else { console.log('file sent') }
});
}
module.exports = productInfo;
script.js - sending a self executing anonymous function
(function(){
// function - load jQuery & Bootstrap in 3rd party website
$masterDiv = $(`
<div>
...
... *data required*
</div>
`)
$('body').append($masterDiv);
// function - jquery event handlers where *data is required*
})();
When some event happens on the third party website page, the event handlers update the right data (id).
How do I pass along data (idList) to script.js?
If I set dummy global variables data before the (function(){})(); line in script.js then I can access it within the function.
I tried res.render but it says "Cannot find module 'js'".
res.render(__dirname + '/scriptproduct.js', (err) => {});
Can I somehow set params to script.js function and call the function with res.send(functionName(idList))?
I have seen answers with templates being sent in html views with res.render but how do I use such a solution in my case where the data is required both in JS and HTML?
I have lots of other routes which are not using a template engine. Can I use it for just one route if that is the solution?
I am very new to all this and basically hacking forward to a solution. So some of my questions above might be elementary.
Using ejs you can pass a string to a EJS template or a .js file. However, you can only pass strings. What you could do is pass the object as a string using JSON.stringify(obj) and then use JSON.parse(obj) to convert it back.
Here's another answer that has some code and may help: How to include external .js file to ejs Node template page
I am new to Node.JS and AngularJS and I have made a connection to a database using Node.js (code below)
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'nodetest'
});
connection.connect();
connection.query('SELECT * from testtable', function(err, rows, fields) {
if (!err) {
var test = rows;
console.log('The solution is: ', test);
return test;
} else{
console.log('Error while performing Query.');
}
});
connection.end();
the database consists of 2 tables (ID and name) and only has 1 row (1, 'Luuk')
my code gets put through Grunt for compiling.
when I run the script stated above, it give the expected result (The solution is: [ RowDataPacket { ID: 1, name: 'Luuk' } ])
but when I want to add this to a controller in angularjs, it gives no results
app.controller('NameController', function() {
this.nameList = test;
});
how would be fixed?
I think that you're confusing concepts.
Angular.js and Node.js are running in a COMPLETELY different environment. Node.js is a server, that is running locally in your machine, which you can access via browser with the url localhost:3000 for example. But this server can be running on another machine for example, which you would be able to access via IP, something like 123.4.5.678:3000.
To share data between the backend and the frontend, you must do this over requests. When you access the localhost via browser, you're doing a request to the server, and the server provide some response, like a HTML page or something like that.
Look this example at the Nodejs Docs
http.createServer( function(request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(3000);
In the response we are returning a plain text. But this can be json, with your search at the database.
And you can do a specific route, like /getTestTable which you can call in the Angular, with the $http service, and handle this.
I suggest to take a better look at how Node.js works, and Angular.js too.
You would like to take a look too at the Express.js, a framework for Node.
Check the scope of variable test - it is defined inside call back function of connection.query. Try defining variable 'test' globally.
I'm having trouble running a Node.js server with Adobe Brackets. Once in live preview (the URL is http://localhost:SOMERANDOMPORT/path/to/file.html), I start the server. If I type http://localhost:3000/test straight into another tab, it displays the correct JSON.
I then added an event function to an element in file.html that upon clicking it makes an AJAX request to my server and uses the response to change some of its inner HTML. However, clicking the element in live preview fails, and the error callback gets called instead.
How can I fix this? I suspect it has to do with the fact that the AJAX request sends to http://localhost:SOMERANDOMPORT/test rather than http://localhost:3000/test, but I can't seem to find a solution.
Everything runs locally. Below is my server:
var express = require('express');
var mysql = require('mysql');
var app = express();
app.get('/test', function(req, res){
var connection = mysql.createConnection(...);
connection.query("SELECT author FROM posts", function(err, results) {
if (err) {
console.log(err);
console.log('Error on retrieving data.');
res.send(err);
return;
}
console.log(results[results.length - 1]);
res.send(results[results.length - 1]); // return last row
});
connection.end();
});
app.listen(3000);
console.log('Listening on port ' + port);
And the event function:
function getAuthor() {
$.ajax({
type: 'GET',
url: '/test',,
success: function(data, status) {
$('.author').text('Authored by ' + data.author);
},
error: function(jqXHR, status, error) { // this always get called
$('.author').text('Something went wrong.');
}
});
}
I appreciate any help.
The simplest fix is to point Live Preview directly at your own Node server, letting it serve up the pages itself from the correct port number (rather than serving the pages from Brackets's built-in server that's on a different port). See instructions on the Brackets wiki under "Using your own backend."
The downside is that HTML live updating is disabled - but you'll still get CSS live updating, and Brackets falls back on a simpler "live reload" on save for HTML content.
To keep live HTML updating enabled you'd need to work around the port number difference somehow. You could hardcode a localhost:3000 base URL for testing, but you'll run same-origin problems due to the port numbers not matching. Working around that would be pretty involved (set up CORS on your Node server, etc.).
One other option for keeping the full Live Preview experience is to shim all your $.ajax() calls so they return hardcoded dummy data without hitting the server. If you're already doing some mocking for unit tests, you might be able to reuse that existing infrastructure for this.
I am using Express.js to build a small application. I have successfully implement the feature that allows me to add new entries to the database.
I am currently trying to delete an entry from a mysql db when a user clicks on a button. This is the code that gets executed:
client.query('DELETE FROM humans WHERE id= ?', [req.params.id], function(err, result) {
if (err) {
throw err;
}
res.redirect('/humans');
I know that the code executes properly because I get redirected to the correct page. Still, my entry is still in the database.
Deducing from the comments to your question I guess that you're sending the id from a form using a POST request. To find post params in req.body (if you're using the express.bodyParser middleware). Thus:
client.query('DELETE FROM humans WHERE id= ?', [req.body.id], function(err, result) {
if (err) {
throw err;
}
res.redirect('/humans');
});
If you're sending a GET request the param would be find in req.query.