I'm trying to pass variables from index.html to my react app which is compiled and running on express/node server locally. I tried using the window object but node.js don't recognize the window object.
Basically once the app is loaded index.html get user info from query string and send data to userController. See code below
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="telephone=no" name="format-detection">
<meta content="no" name="msapplication-tap-highlight">
<meta content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width" name="viewport">
<title>App Frontend</title>
</head>
<body>
<div id="root"></div>
<script src="js/compiledscript.js"></script>
<script>
new AppCode({
root: document.getElementById('root'),
host: 'http://localhost:3500',
endpoints: {
folder: '/api/folder',
file: '/api/file'
},
headers: {
'Content-Type': 'application/json'
}
});
//Get iframe data query from parent
function getParamValue(paramName)
{
var url = window.location.search.substring(1); //get rid of "?" in querystring
var qArray = url.split('&'); //get key-value pairs
for (var i = 0; i < qArray.length; i++)
{
var pArr = qArray[i].split('='); //split key and value
if (pArr[0] == paramName)
return pArr[1]; //return value
}
}
var userData = {
username: getParamValue('username'),
userid: getParamValue('userid')
}
window.userData = userData;
//console.log(getParamValue('username'));
//console.log(getParamValue('userid'));
</script>
</body>
</html>
userController.js
const mongoose = require('mongoose');
const path = require('path');
const fs = require('fs');
const User = mongoose.model('User');
//const users = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'data', 'users.json'), 'utf-8'));
/*
const users = window.userData;
const userid = users.userid;
exports.userid = userid;
*/
exports.getAll = async (req, res) => {
const users = await User.find();
res.json(users);
};
exports.bang = async (req, res, next) => {
await User.remove();
next();
};
exports.addNewUser = async (req, res, next) => {
await User.create(users);
// next();
};
If you are sending the HTML file as static file,
You Can do this solution:
Solution:
install ejs by running the command npm i ejs then change your file from index.html to index.ejs,
add this line to your app
app.set('view engine', 'ejs');
and send the file by
res.render('index.ejs', {
// here data to pass
});
then you can pass data to index.ejs and it will get rendered
you can read the docs in here it will clarify the image more.
if you can use server-side rendering
then redux would be the solution
Related
I am trying through node js, express and mongoose to create a way to add the same mongoose Schema more than one time I want to use a trigger button. I have to restart the server to add more to the DB.
Later on I want to change it through a counter but first I need to get this working.
I am trying to solve it on my own but I got stuck, thank you for your help !
the app.js I use as server.
/app.js
const express = require('express');
const { default: mongoose } = require('mongoose');
const path = require('path');
const db = require("./database");
const app = express();
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.use(express.static('DB'));
app.use('/Dev', express.static(path.join(__dirname, 'Dev', 'public')));
//Export function to new a .js file
var ClickyClicky = new mongoose.Schema({
name: {
type: String,
require: true
}},
{
timestamps: true, //time
}
);
var Clicky = mongoose.model('Click', ClickyClicky, 'clickystore');
var Clicks = new Clicky({ name: 'Test' });
//Export function to new a .js file
//Save button trigger.
app.post('/test', (req, res) => {
Clicks.save(function (err, book) {
if (err) return console.error(err);
console.log(book.name + " saved to bookstore collection.");
});
});
//Save button trigger.
app.post('/alfa', (req, res) => {
Clicks.save(function (err, name) {
if (err) return console.error(err);
console.log(name.name + " saved to name collection.");
});
});
// // 404 page
app.all('*', (req, res) => {
res.status(404).send('<h1>404, Page not found !</h1>');
});
app.listen(5000, () => {
console.log('Server started at http://localhost:5000');
});
/client.js
console.log('Client code running');
const testButton = document.getElementById('Button');
testButton.addEventListener('click', function(e) {
console.log('Butten was clicked');
fetch('/test', {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);
});
});
const testButton2 = document.getElementById('Button2');
testButton2.addEventListener('click', function(e) {
console.log('Butten was clicked');
fetch('/alfa', {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);
});
});
index.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>
<button id="Button">Click me for a test!</button>
<button id="Button2">Click me for a test1!</button>
</body>
<script src="./Dev/Client.js"></script>
</html>
\database.js
require('dotenv').config();
const mongoose = require('mongoose');
mongoose.set("strictQuery", false);
mongoose.connect(process.env.MONGOOB_URI, () => {
console.log("Connected to MongoDB");
});
I solved my issue with adding, unique: false to my mongoose schema and deleted the old input from the BD
i am testing this url==> (http://localhost:8800/api/users/634ed4af41fb0169e999deb2/follow) on
postman, it works in case of without having (/follow), But when i use this url every time i get this error=====>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot PUT /api/users/634ed4af41fb0169e999deb2/follow%0A</pre>
</body>
</html>
Below i am getting issue in using // app.use('/api/users',userRoutes)//. This will call the router present in the users.js
index.js
const express= require("express");
const app=express();
const mongoose=require("mongoose");
const dotenv=require("dotenv");
const helmet=require("helmet");
const morgan=require("morgan");
const userRoutes=require("./routes/users")
const authRoutes=require("./routes/auth");
dotenv.config();
mongoose.connect(process.env.MONGO_URL,
{useNewUrlParser: true, useUnifiedTopology: true}, ()=>{
console.log("connected to database");
});
//middleware
app.use(express.json());
app.use(helmet());
app.use(morgan("common"));
//cutom middleware for Routing
app.use('/api/users',userRoutes);
app.use('/api/auth',authRoutes);
app.listen(8800,()=>{
console.log("backend server running");
})
here in user.js controller are not able to log the console present at the top position.
user.js
const router=require("express").Router();
const bcrypt=require('bcrypt');
const User = require("../models/User");
//follow user
router.put("/:id/follow", async (req , res)=>{
console.log(req.body.userId === req.params.id.trim());
if(req.body.userId !== req.params.id){
try {
const user= await User.findById(req.params.id);
const currentUser= await User.findById(req.body.userId);
if(!user.followers.includes(req.body.userId)){
await user.updateOne({$push:{followers:req.body.userId}});
await currentUser.updateOne({$push:{followings:req.params.id}});
res.status(200).json("user has been follwed")
}else{
res.status(403).json('you all ready followed')
}
} catch (error) {
res.status(500).json(error)
}
}
else{
res.status(403).json("you cant follow yourself")
}
})
I'm using MEAN stack as my back-end. this is my server js file
const users = require('./routes/users');
app.get('/', (req, res) => {
res.send('Invalid endpoint');
});
This is my routes file users.js
router.get('/jobdetail', function(req,res) {
console.log('fetching jobs');
jobDetails.find({}, (err,jobs) => {
if(err) {
console.log(err);
}
else {
res.json(jobs);
}
});
});
when I run it the postman bu url:
localhost:3000/api/jobdetail
Instead of the data from MongoDB I get the response as
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
<script type="text/javascript" src="http://gc.kis.v2.scr.kaspersky-labs.com/D11634C0-514E-C94E-9DFD-54EBD0B16E5F/main.js" charset="UTF-8"></script>
</head>
<body>
<pre>Cannot GET /api/jobdetail</pre>
</body>
</html>
var api = require('../routes/users.js');
app.use('/api', api);
in your routes/users.js file :
var mongoose =require('mongoose');
var router = require('express').Router();
var conn = mongoose.connection;
conn.once("open", () => {
router.get('/jobdetail', function(req, res) {
jobDetails.find({}, (err,jobs) => {
if(err) {
console.log(err);
}
else {
res.json(jobs);
}
});
});
});
module.exports = router;
Here is my sample code:
File: index.js
var express = required('express');
var app = express();
app.get("/", function(req, res){
...
...
res.render("/index", {
list: data
});
});
File: test.js
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('../index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function(done){
it('should render index view', function(done){
chai.request(server.app)
.get("/")
.end(function(err, res){
console.log(res.body);
});
});
});
The console.log(res.body) shows output as {}. How can I get the local list variable to show in the output? I want to test if this local list variable has any data in my test.js file.
Option 1. You should use res.json([body]) to send the list data to your test case.
E.g.
index.js:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
const data = ['a', 'b'];
res.json({ list: data });
});
module.exports = { app };
index.test.js:
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('./index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function (done) {
it('should render index view', function (done) {
chai
.request(server.app)
.get('/')
.end(function (err, res) {
console.log(res.body);
done();
});
});
});
test result:
Homepage
{ list: [ 'a', 'b' ] }
✓ should render index view
1 passing (28ms)
Option 2. You should assert the view rendered correctly with your list data.
index.js:
var express = require('express');
var path = require('path');
var app = express();
app.set('views', path.resolve(__dirname, './views'));
app.set('view engine', 'ejs');
app.get('/', function (req, res) {
const data = ['a', 'b'];
res.render('index', { list: data });
});
module.exports = { app };
views/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<% for (let v of list) { %>
<p><%= v %></p>
<% } %>
</body>
</html>
index.test.js:
const { expect } = require('chai');
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('./index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function (done) {
it('should render index view', function (done) {
chai
.request(server.app)
.get('/')
.end(function (err, res) {
console.log(res.text);
done();
});
});
});
test result:
Homepage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>a</p>
<p>b</p>
</body>
</html>
✓ should render index view
1 passing (32ms)
I was thinking there should be an fs.files.findAll() so I could get all the file names and display it on the page. right now I could only find one at I time and I could display them. I want to have an index page with all the images in the DB.
const mongoose = require("mongoose");
const Grid = require("gridfs-stream");
const fs = require("fs");
const express = require("express");
const app = express("/")
mongoose.connect("mongodb://localhost/newDb");
const conn = mongoose.connection;
app.set("view engine", "ejs"); // set the view engine
app.use(express.static("public"));
const uploadImages = require("./uploadImages");
const getAllImages = require("./getAllImages");
console.log(mongoose.connection.readyState);
app.get("/:img", (req, res) => {
getAllImages(conn, req.params.img, res)
})
app.get("/", (req, res) => {
//render all images on page
//how do I find how many images are in the DB
//and to get the file names to pass to ejs
//so I could do forloop to get // img src "/image1.jpg"
})
app.listen(3000, (err) => {
console.log("listening on port 3000")
})
In getAllImages
const mongoose = require("mongoose");
const Grid = require("gridfs-stream");
const fs = require("fs")
function getAllImages(conn, img, response){
const gfs = Grid(mongoose.connection.db, mongoose.mongo);
const readStream = gfs.createReadStream({
filename :img
})
readStream.on("error" , function(err){
console.log("An error: ", err);
})
readStream.pipe(response);
// mongoose.connection.db.listCollections( (err, names) => {
// console.log(names);
// })
}
module.exports = getAllImages;
This is how I did it:
const Schema = mongoose.Schema;
const Image = mongoose.model("Image",
new Schema({filename : String, contentType : String, uploadDate : Date}),
"fs.files"
);
then
app.get("/", (req, res) => {
Image.find()
.then((docs) =>{
var imageNames = docs.map((e) => {
return e.filename
})
res.render("index", {
imageNames
})
console.log(docs)
})
})
in index
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
</head>
<body>
<h1>Hello</h1>
<% imageNames.forEach((e) =>{ %>
<a href = <%=e %>><%=e.split(".")[0]%></a>
<img src = "/<%=e%>"> <br>
<%})%>
</body>
</html>
I didn't want to set up the mongoose mode. I heard mongoose needs that. Is there another way using gridf-stream?