I want to transmit my data to client-side JS file from the server, but right now the browser displays data on its main screen like when we use innerHTML property:
I have checked bunch of express.js tutorials but seems like there are no way to send (add, technically) data to the client side js file.
This is a diagram what I'm looking for:
[open the webpage] -> [(in server) get data from database] -> [send data to client-side js file] -> // do stuff more in the client-side
Any tips to resolve this problem?
This is my code:
// Makes display the client-side html, temporary disabled.
// app.use(express.static('client'));
// Queries
const QUERIES = {
prev: 'SELECT * FROM en.prevstore',
curr: 'SELECT * FROM en.currstore',
next: 'SELECT * FROM en.nextstore',
samp: 'SELECT * FROM en.sample'
}
// Create connection
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password123',
database: 'en'
});
// Router
app.use('/', (req, res) => {
db.query(QUERIES.samp, (err, results) => {
let ternary = err ? console.error(err) : res.json(results);
})
})
Client-Side HTML (request from the comment)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div class="quotes">
should be filled as quotes of data from database
</div>
<div class="color">
should be filled as color of data from database
</div>
<script type="text/javascript" src="./index.js"></script>
</body>
</html>
Client-Side JS:
function getWord() {
fetch('http://localhost:4000')
.then(res => res.json())
.then(({data}) => console.log(data))
}
getWord() // I know it won't work but tried for just in case.
When you tried to load localhost:4000 on your browser and it is requesting your / endpoint.
Your server has to return your static files (index.html & ...) on this endpoint.
app.use(express.static('public'));
// public or any static directory containing your index.html, .js, images ...
Then you can move your / endpoint to something more explicit like /quotes
app.use('/quotes', (req, res) => {
db.query(QUERIES.samp, (err, results) => {
if (err) {
console.log('error', err);
res.status(500);
return res.end(); // closing the response /!\ IMPORTANT
}
res.json(results);
})
})
On your client-side you will have something like that:
function getWord() {
fetch('http://localhost:4000/quotes')
.then(res => res.json())
.then(data => console.log(data))
}
Related
I'm hosting a web app on localhost:3000 via NodeJS (with MySQL database via WAMP). Front end has a button to insert a record into a MySQL database table (called tblbacktrack). It runs the query as expected exactly 6 times, then stops working altogether, without an error or crash. 6 times, every time. If I change the query to a delete, same problem: 6 deletions is all I get until I refresh the page via the browser.
App2.js:
const express = require('express');
const mysql = require('mysql');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
// create connection
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'journey_test'
})
// connect to mysql
db.connect(err => {
if(err) {
throw err
}
console.log('MySQL Connected');
})
const app = express()
app.use(express.static('public'));
app.set('view engine', 'ejs');
// This pulls index.ejs to the root folder location of the site.
app.get('/', function (req, res) {
res.render('index2');
});
app.post('/deleteBtDb/', upload.none(), function (req, res, next) {
// let sql = `DELETE from tblbacktrack limit 1`
let sql = `INSERT into tblbacktrack (btEntryNum, btDate) values ('E: 19810809', '2021-05-05');`
let query = db.query(sql, (err, results) => {
if(err) {
throw err
}
})
})
// Let the console know that the server has started on port 3000
app.listen('3000', () => {
console.log('Server Started on port 3000')
})
index2.ejs:
<!DOCTYPE html>
<html>
<head>
<link href="/css/style.css" rel="stylesheet" type="text/css" media="all" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="container">
<div class="Header">
</div>
<div class="Footer"></div>
<div class="Middle">
<div id="Middle-Center" class="Middle-Center"></div>
<div id="Middle-Left" class="Middle-Left"></div>
<div id="Middle-Right" class="Middle-Right"><%- include ('../views/middle-right'); %></div>
</div>
</div>
</body>
Middle-right.ejs:
<div><button onclick="deleteBtDb()">Click me</button></div>
<script>
function deleteBtDb() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "./deleteBtDb/", true);
xhttp.send();
}
</script>
If I run the same queries in phpMyAdmin, they work, and I can definitely run them successfully more than 6 times there. If I set up a for loop in app2.js, such that a single click of the index2.ejs button should insert 10 new records, it successfully inserts 10 new records. Please help! I don't know how to further troubleshoot this.
Solved it!
I wasn't using a "res" object in there. Added "res.status(201).json()", and it's all better now.
app.post('/deleteBtDb/', upload.none(), function (req, res, next) {
let sql = `DELETE from tblbacktrack order by btID ASC limit 1`
let query = db.query(sql, (err, results) => {
if(err) {
throw err
}
})
res.status(201).json();
})
I have DATA stored in mysql.
And I want to display it in a table in HTML.
I am currently using NODE.JS AND EXPRESS.
How can I save the DATA that comes in and put it into a table in HTML.
I was trying to find a way to save this DATA,
And use a MAP loop inside a script tag in HTML,
But I could not send the DATA to HTML .
app.js
const mysql = require('mysql')
const SQL = require('sql-template-strings')
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const port = 3000
const Joi = require('joi');
app.use(bodyParser.urlencoded({ extended: true }))
// connect to MySQL
const con = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'pass123',
database: 'carStorege'
})
con.connect((err)=> {
if(err) throw err;
else console.log('connect to DB !')
})
// seva data from database
con.query("SELECT * from Cars", (err, result, fields) => {
if(err) console.log(err);
else {
//save the data
const data = result
}
})
// express
// url to see all the car in table
app.get('/all', (req, res) => {
con.query("SELECT * from Cars", (err, result, fields) => {
if(err) throw err;
else {
res.sendFile(__dirname+'/allCars.html')
}
})
})
app.listen(port, () => console.log('srever is live'))
and this is the HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<tr>
<th>Car manufacturer</th>
<th>Car model</th>
<th>Color</th>
<th>Yaer</th>
<th>Price</th>
<th>Door number</th>
</tr>
// here the data shuld be
</body>
</html>
This needs to be done in front-end javascript. The JS on your webpage (connected to the HTML) needs to request the data from your Node server, then doSomething with it. It will likely be in an array, so you can just loop through the array, create a new HTML row with the data in it, and append that to the correct spot in your table. Something like:
fetch('http://yourWebSite.com/api/all')
.then(response => response.json())
.then(data => {
console.log(data);
let table = document.querySelector('#tableId')
data.forEach(row => {
let tr = document.createElement('tr');
tr.appendChild(document.createElement('th').innerText(row.item1))
tr.appendChild(document.createElement('th').innerText(row.item2))
tr.appendChild(document.createElement('th').innerText(row.item3))
table.appendChild(tr)
})
});
This is where frameworks come in handy, since a library like React, Vue, or Angular have rendering strategies that are designed to handle this.
I created a simple API on a node server. The server is running on the port 9000. I created an endpoint called getUserDetails and I'm passing a simple object. The problem is I can access the API from the browser by entering the full URL 'http://localhost:9000/getUserDetails'.
But I cannot access the API in another HTML file. To elaborate, I created a simple HTML file to test out this API.
My node server:
const app = express();
app.get('/getUserDetails', (req, res) => {
res.send({
firstname : 'Giri',
secondname: 'Aakula',
dob: '15-09-1997',
age: 22,
qualification : 'Graduate',
status : 'pass'
})
})
app.listen(9000);
My HTML file
<!DOCTYPE html>
<html>
<head>
<title>Test page</title>
<style>
h1{
font-size: 50px;
}
</style>
</head>
<script>
fetch('http://localhost:9000/getUserDetails')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
});
</script>
<body>
<h1>This is a test page</h1>
</body>
</html>
I forgot to add cors. By adding this one line fixed my issue.
const express = require('express');
const app = express();
app.get('/getUserDetails', (req, res) => {
//this is the updated line
res.setHeader('Access-Control-Allow-Origin', '*');
res.send({
firstname : 'Giri',
secondname: 'Aakula',
dob: '15-09-1997',
age: 22,
qualification : 'Graduate',
status : 'pass'
})
})
app.listen(9000);
I am trying to upload an image from the front-end, post it with axios to back-end (node.js) and then from there post it again to the GroupMe image service.
The main thing is to avoid using the API token in the front-end and so I was trying to first send a request to the back-end and then send the actual API request to the GroupMe image service which expects to get FormData of an image and sends back converted image URL.
I have tried to send FormData directly to the GroupMe image service from the front-end and everything works fine. However, in order to do so, I had to store the token in the front-end, which is not a good idea I believe.
The working code below:
let config = {
headers : {
'X-Access-Token': myToken,
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post'(https://image.groupme.com/pictures', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
What I need to happen instead is to send the request to the back-end like so:
axios.post(process.env.baseUrl+'/messengerRequests/upload-file/', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
And now in the back-end somehow be able to get that FormData and then create another post request to the GroupMe image service as I initially did in the front-end.
sendMessage: async(req, res) => {
axios.post('https://image.groupme.com/pictures', ???, config)
.then((response)=>{
res.send(response)
})
.catch(err =>{
console.log(err.response)
})
}
I do not know where it appears in the axios request. There is nothing in the req.body or req.params so I am not able to simply pass it further for the next post.
Is there a way somehow pass this FormData again?
Or maybe there is a way to safely use the token in the frond-end?
So, it should be relatively straightforward to post the image to GroupMe using Node.js and Express / Multer / Request. I've gone for Request rather than Axios on the backend since I'm more familiar with the API, but it's the same difference really.
Node.js Code (index.js)
const request = require("request");
const express = require("express");
const multer = require("multer");
const upload = multer();
const app = express();
const port = 3000;
const myToken = "" // Your API token goes here.
app.use(express.static("./"));
/* Here we take the image from the client and pass it on to GroupMe */
app.post("/uploadFile", upload.any(), (req, res) => {
sendImageToGroupMe(req, res);
});
function sendImageToGroupMe(req, res) {
const options = {
uri: "https://image.groupme.com/pictures",
body: req.files[0].buffer,
method: "POST",
headers: {
"X-Access-Token" : myToken
}
}
request(options, (err, response, body) => {
console.log("Request complete: Response: ", body);
if (err) {
console.error("Request err: ", err);
res.status(500).send("Upload failed: ", err.message);
} else {
res.status(201).send("Upload successful: GroupMe response: " + body);
}
});
}
app.listen(port);
Client side
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function uploadFile() {
var fileToUpload = document.querySelector('input[type=file]').files[0];
let config = {
headers : {
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post('http://localhost:3000/uploadFile', fd, config)
.then((response)=>{
console.log("Image posted successfully: ", response);
showOutput("Image posted successfully: " + response.data);
})
.catch(err =>{
console.error("Image post failed: ", err)
showOutput("Image post failed!");
})
}
function showOutput(html) {
document.getElementById("output").innerHTML = html;
}
</script>
</head>
<body style="margin:50px">
<input type="file" onchange="uploadFile()"><br>
<p id="output"></p>
</body>
</html>
All files go in the same directory. You can go to http://localhost:3000/ to test the index.html code, this will be served by the Node.js server as a static file.
I get a response like below from the GroupMe API:
{
"payload": {
"url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971",
"picture_url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971"
}
}
We'll serve locally on port 3000, so to start the server:
node index.js
If you are using Express, you will need something to process the FormData. I have used multer for something similar before. I had to save the files into local storage, then resend the file with axios.
I have a button in my frontend, and am using nodejs and express on my server-side backend. I have a function (essentially controlling Philips Hue API) on the backend, and I would like it to be executed when the button is clicked, through a http request.
I have tried different methods. the backend script for the Philips Hue controls work independently when i extract it and run it in git bash. I think there's some conceptual or coding errors on end.
Html Button
<button id="pulse" type="button" class="btn btn-danger">Pulsing Lights</button>
Client side JS
const pulseButton = document.getElementById("pulse");
pulseButton.addEventListener('click', function() {
fetch('/huePulseLight', {method: 'POST'})
.then(function(response) {
if(response.ok) {
console.log('Click was recorded');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
});
Backend/Server Side JS
const port = 3000;
const server = http.Server(app);
server.listen(process.env.PORT || 3000, function(){
console.log('Server running on port ' + port);
});
const app = express();
pulseLight = lightState.create().on().colorLoop();
function setPulseLight() {
nodeHueapi.setLightState(1, pulseLight, function (err, lights) {
if (err) throw err;
displayResult(lights);
});
nodeHueapi.setLightState(2, pulseLight, function (err, lights) {
if (err) throw err;
displayResult(lights);
});
nodeHueapi.setLightState(3, pulseLight, function (err, lights) {
if (err) throw err;
displayResult(lights);
});
}
app.post('/huePulseLight', function(req, res){
console.log("Pulse Light Set");
setPulseLight();
});
Isolate the problem. Make sure both your server and browser consoles are communicating properly before adding anything else. This is more-or-less the minimum code for the client and server to communicate. Run node server.js in test, navigate to localhost:3000, click the text, observe the console outputs.
test/server.js
const express = require("express")
const app = express()
// make index.html accessible to clients
app.use(express.static('public'))
app.post('/huePulseLight', function(request, response){
console.log("Pulse Light Set");
response.send("Click Recorded")
});
app.listen(3000)
test/public/index.html
<html>
<head></head>
</body>
<p id="pulse">foo</p>
<script>
const pulseButton = document.getElementById("pulse")
pulseButton.addEventListener('click', function() {
fetch('/huePulseLight', {method: 'POST'})
.then(response => response.text())
.then(text => console.log(text))
})
</script>
</body>
</html>
You are missing app.listen(PORT) on your server.
Also, you're not sending back anything from the server to the client, that might cause the client to keep the connection open with the server and your fetch promise will never resolved.