Can't store my new generated data in MongoDB - javascript

I am building a small project where you can generate a random hex color and then save it to database. But I don't know what I am doing wrong because my data won't save to database.
So index.js is my main file where I am declaring routes. I am using ejs for templeting and a separate file in a public folder where I write my javascript code. Can you give me a hint? Should I somehow work on my JS file where I click the button to submit the hex code somewhere?
index.js
const express = require('express');
const app = express();
const path = require('path');
const mongoose = require('mongoose');
const Color = require('./models/hexColor');
mongoose.connect('mongodb://localhost:27017/randColor', {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => {
console.log("MONGO CONNECTION OPEN")
})
.catch(err => {
console.log("ERROR MONGO CONNECTION")
console.log(err)
})
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use('/public', express.static('public'));
app.use(express.urlencoded({extended: true}));
app.get('/home', (req, res) => {
res.render('homepage.ejs')
})
app.get('/hexColor', async (req, res) => {
const color = await Color.find({});
res.render('hexColor.ejs', { color });
})
app.post('/hexColor', async (req, res) => {
const newColor = new Color(req.body)
await newColor.save();
})
app.listen(3000, () => {
console.log("Listening!")
})
hexColor.ejs
<!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">
<link rel="stylesheet" href="../public/hexColor.css">
<title>Hex Color Generator</title>
</head>
<body>
<form action="/hexColor" method="POST">
<div class="nav-container">
<div>
<h4 class="back-to-home">Home</h4>
</div>
<div>
<h1>Hex Color Generator</h1>
</div>
<div>
<h4>History</h4>
</div>
</div>
<div class="btn-container">
<button class="btn-generator">Click to generate</button>
</div>
<div class="color-container">
<div class="square-container">
</div>
</div>
<ul class="hex"></ul>
</form>
<script src="../public/hexColor.js"></script>
</body>
</html
hexColor.ejs
const homeBtn = document.querySelector(".back-to-home");
const btnGenerator = document.querySelector(".btn-generator");
const squareCont = document.querySelector(".square-container");
const ul = document.querySelector('.hex');
function hexChangeColor () {
var randomColor = Math.floor(Math.random()*16777215).toString(16);
var hexColor = `#${randomColor}`;
return hexColor;
}
homeBtn.addEventListener('click', function () {
window.location.href = 'http://localhost:3000/home'
})
btnGenerator.addEventListener('click', function (e) {
e.preventDefault();
squareCont.style.backgroundColor = hexChangeColor();
const li = document.createElement('LI');
li.innerHTML = hexChangeColor();
ul.appendChild(li);
})
hexSchema.js
const mongoose = require('mongoose');
const colorSchema = new mongoose.Schema({
hex: {
type: String
}
})
const Color = mongoose.model('Color', colorSchema);
module.exports = Color;

what you are getting in req.body?
Try by adding body-parser
https://www.npmjs.com/package/body-parser

Related

Cast to ObjectId failed for value "XXXX" (type string) at path "_id" for model "XXXXX"

I have created a form that takes image url from user and stores it in MongoDB, but when I try to insert the link from the db via ejs the app crashes displaying this error " Cast to ObjectId failed for value "XXXX" (type string) at path "_id" for model "XXXXX" "
This problem appears only with the image, it works perfectly fine with anchor tags or other elements.
JavaScript
const express = require('express');
const path = require('path');
const ejs = require('ejs');
const ejsMate = require('ejs-mate');
const methodOverride = require('method-override');
const mongoose = require('mongoose');
const LandingPage = require('./models/landingpage')
const app = express();
mongoose.connect('mongodb://localhost:27017/landing-page', {
useNewUrlParser: true,
useUnifiedTopology: true
});
const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", () => {
console.log("Database connected");
});
app.engine('ejs', ejsMate)
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'))
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')))
app.get('/',(req,res)=>{
res.render('index');
})
app.get('/create',(req,res)=>{
res.render('create');
})
app.post('/', async (req,res)=>{
const landingPage = new LandingPage(req.body.LandingPage);
landingPage.title = req.body.title;
landingPage.image = req.body.image;
landingPage.aflink = req.body.aflink;
landingPage.description = req.body.description;
await landingPage.save();
res.redirect(`/pages/${landingPage._id}`);
})
app.get('/pages',(req,res)=>{
res.render('pages');
})
app.get('/pages/:id', async (req,res)=>{
const {id} = req.params;
const landingPage = await LandingPage.findById(id);
res.render('landingpage',{landingPage});
})
app.listen('3000',()=>{
console.log('Listening on port 3000');
})
Html/ejs
<!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>
<h1><%=landingPage.title%></h1>
<img src=" <%=landingPage.image%> " alt=""> // When I remove this line the app works again
Press here
<h2><%=landingPage.description%></h2>
</body>
</html>

Node.js send input text to python script for processing and writing the output on a div on the same page

I am trying to take text from an HTML input field and send it via POST-request to a python script for processing (I am using child process).
Right now, I am just sending the processed data to the response and overwriting the index.html, but I would like to just write the output of the python script into a text field under the input field in the same endpoint ("/").
Is there a way of doing this without having to re-render the entire HTML with just the new text added to it?
server.js:
const express = require("express");
const { spawn } = require("child_process");
const path = require("path");
const bodyParser = require("body-parser");
const router = express()
const app = express();
const port = 3000;
app.use(bodyParser.urlencoded({extended:true}));
app.get("/", (req, res) => {
res.sendFile(path.join( __dirname+'/index.html'));
});
app.post("/", (req, res) => {
// This is where the text field data is parsed into the python script
const python = spawn("python", ["script.py", req.body.sentence]);
python.stdout.on("data", function (data) {
processed_data = data.toString();
});
python.stderr.on("data", data => {
console.error(`stderr: ${data}`);
})
python.on("exit", (code) => {
// Something else here possibly?
res.send(processed_data);
});
})
app.listen(port, () => console.log(`App listening on port ${port}!`));
index.html:
<form method="POST" action="/">
<fieldset>
<label>Write a sentence:</label>
<input type="text" id="sentence" name="sentence" required>
<br><br>
<button type ="submit">Run</button>
<br><br>
<textfield id=output_field><textfield>
</fieldset>
</form>
script.py can really do anything here:
import sys
sentence = sys.argv[1]
print(sentence , " this is stuff added to the sentence")
sys.stdout.flush()
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>
<fieldset>
<label>Write a sentence:</label>
<input type="text" id="sentence" name="sentence" required>
<br><br>
<button id='buttonFetch'>Run</button>
<br><br>
<textfield id="output_field"><textfield>
</fieldset>
<script>
const button = document.querySelector("#buttonFetch")
button.addEventListener("click", () => {
const sentence = document.querySelector("#sentence").value
fetch("http://localhost:3000/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
sentence
}),
})
.then(res => res.text())
.then(data => {
console.log(data)
const output_field = document.querySelector("#output_field")
output_field.textContent = data
})
.catch(e => {
console.error(e.error)
})
})
</script>
</body>
</html>
server.js (I removed bodyParser and add express.json())
'use strict'
const express = require("express");
const { spawn } = require("child_process");
const path = require("path");
//const bodyParser = require("body-parser");
const router = express()
const app = express();
const port = 3000;
app.use(express.json())
//app.use(bodyParser.urlencoded({extended:true}));
app.get("/", (req, res) => {
res.sendFile(path.join( __dirname+'/index.html'));
});
app.post("/", (req, res) => {
console.log(`req.body.sentence: ${req.body.sentence}`)
// This is where the text field data is parsed into the python script
const python = spawn("python", ["script.py", req.body.sentence]);
let processed_data = ''
python.stdout.on("data", function (data) {
processed_data = data.toString();
});
python.stderr.on("data", data => {
console.error(`stderr: ${data}`);
})
python.on("exit", (code) => {
// Something else here possibly?
console.log(processed_data)
res.send(processed_data);
});
})
app.listen(port, () => console.log(`App listening on port ${port}!`));

using socket.io with express router

I am fairly new to node.js, I am trying to build a webchat and so far I have a server.js file and a router.js file that should have all my routes inside. I am not using express-generator. I would like to use socket.io but on my current setup it doesn't work.
Here is what I have
server.js
const path = require('path');
const express = require('express');
const layout = require('express-layout');
const app = express();
const routes = require('./router');
const bodyParser = require('body-parser');
var server = require('http').createServer(app);
var io=require('socket.io')(server);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
const middleware = [
layout(),
express.static(path.join(__dirname, 'public')),
bodyParser.urlencoded(),
];
app.use(middleware);
app.use('/', routes);
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!");
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
io.on('connection',function (socket) {
console.log('yo');
});
server.listen(3000, () => {
console.log(`App running at http://localhost:3000`);
});
router.js
const express = require('express');
const router = express.Router();
const {check, validationResult}=require('express-validator');
const { matchedData } = require('express-validator/filter')
const app = express();
router.get('/', (req, res) => {
res.render('index', {
data: {},
errors: {}
})
});
router.post('/enter', [
check('username')
.isLength({min: 1})
.withMessage('Username is required') //implement personalized check
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.render('index', {
data: req.body,
errors: errors.mapped()
})
}
const data = matchedData(req)
});
module.exports = router;
It should log "yo" on the console but it doesn't. I already tried to move the socket.io setup part to router.js, it doesn't give any errors but it does not log anything. Also if I set up correctly socket.io on my server.js, how do I pass it to router.js?
EDIT
there is the index.ejs file that has some client code that initializes the connection with socket.io
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Global.io</title>
<link type="text/css" rel="stylesheet" href="/index.css">
<script>
var socket = io();
socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
console.log('yo client');
});
</script>
<!-- <script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script src="/scripts/client.js" defer></script> -->
</head>
<body>
<h1>Start debating about the change</h1>
<div id="wrapper">
<form id="formElem" method="post" action="/enter" novalidate>
<% if (errors.username) { %>
<div class="error"><%= errors.username.msg %></div>
<% } %>
<input id='name' type="text" name="user" placeholder="User name" class=" <%= errors.username ? 'form-field-invalid' : ''%>">
<select name="room" id="room">
</select>
<button type="submit" id="submit-b">Submit</button>
</form>
</div>
</body>
</html>
Now it gives an error saying io is undefined.
You need this:
<script src="/socket.io/socket.io.js"></script>
Before the script that tries to use socket.io in your web page. That script loads the socket.io library and defines the io symbol so you can then use it after the library has been loaded.

why the REST API as a body gets undefined?

I writirng server in Express to posibility GET and POST. In Insomnia I get and post valid data.
This is code my REST.
const express = require('express');
const app = express();
const port = 3000;
var cors = require('cors');
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({extended: true}));
let myValue = 1;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
//GET
app.get('/get', (req, res) => {
return res.json({"wartosc": myValue})
});
//POST
app.post('/post', function (req, res) {
myValue = req.body.value;
console.log(req.body)
return res.json({"wartosc": myValue});
});
Then I creaeted page with two input will be used to call the GET and POST methods of our REST server.
async function getMethod() {
let inputValue = document.getElementById("inputValue").value;
const responseGet = await fetch('http://localhost:3000/get');
const myJsonGet = await responseGet.json();
//console.log(JSON.stringify(myJsonGet));
document.getElementById("inputValue").value = myJsonGet.wartosc;
}
async function postMethod(){
let inputValue = document.getElementById("inputValue").value;
let responsePost = await fetch('http://localhost:3000/post', {
method: 'POST',
body: {'value' : JSON.stringify(inputValue)}
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text" id="inputValue">
<button onclick="getMethod()"> GET</button>
<button onclick="postMethod()">POST</button>
<script src="script.js"></script>
</body>
</html>
When I do get , I get the correct value, but when I change the value and send a post, the server prints undefined.
I don't know why, will you try to help me?
In your script.js postMethod() you should stringify the entire body:
body: JSON.stringify({'value' : inputValue})
Ideally you use querystring.stringify instead but this should also work fine.
Alternatively, you can just leave out the entire script.js with the async stuff.
Instead try with using a form and name="value". You can change the form action and method per button.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form method="GET" action="http://localhost:3000/get">
<input type="text" id="value" name="value">
<button type="submit">GET</button>
<button type="submit" formmethod="post" formaction="http://localhost:3000/post">POST</button>
</form>
</body>
</html>
I did some changes to make it work on CodeSandbox (example). Everything works.
const express = require("express");
const app = express();
const port = 3000;
var cors = require("cors");
const rand = () =>
Math.random()
.toString(36)
.substr(2);
app.use(express.static("public"));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
//GET
app.get("/get", (req, res) => {
return res.json({ getval: rand() });
});
//POST
app.post("/post", function(req, res) {
return res.json({ postval: `${rand()}:${req.body.value}` });
});
I put HTML and JavaScript files in the public directory.
async function getMethod() {
const responseGet = await fetch("/get");
const myJsonGet = await responseGet.json();
document.getElementById("inputValue").value = myJsonGet.getval;
}
async function postMethod() {
let inputValue = document.getElementById("inputValue").value;
let options = {
method: "POST",
body: JSON.stringify({ value: inputValue }),
headers: {
"Content-Type": "application/json"
}
};
let responsePost = await fetch("/post", options);
let myJsonPost = await responsePost.json();
document.getElementById("inputValue").value = myJsonPost.postval;
}
Both when you send JSON data via GET and POST, you must extract it with response.json(). In addition, when submitting POST data, you must set a header that is JSON. Without it, the server will not recognize that the transmitted data is in this format.

Displaying Contents of Mongodb Database on webpage

I am trying to display the contents of my database on a webpage.
The way I want to do it is by displaying the content in the database by descending order. I have made the connection to MongoDB and am able to see my data in the terminal stored correctly. I just can't seem to figure out how to display that stored data now.
Thanks!
Server.js file.
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: true })
var mongoose = require("mongoose");
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost:27017/node-demo");
var nameSchema = new mongoose.Schema({
Alert: String
});
var User = mongoose.model("User", nameSchema);
app.listen(3000, function() {
console.log('listening on 3000')
})
app.use(express.static(__dirname + '/public'));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
app.get('/alertview', (req, res) => {
res.sendFile(__dirname + '/alertview.html')
})
app.post('/', urlencodedParser, function (req, res) {
var myData = new User(req.body);
myData.save()
.then(item => {
res.send("item saved to database");
})
.catch(err => {
res.status(400).send("unable to save to database");
});
});
User.find({},function(err,docs){
console.log(docs);
})
Html file I want to display the alerts on.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="/alertpageStyle.css" media="screen" />
<meta charset="UTF-8">
<title>View Alerts</title>
</head>
<body>
<div class="header">
<h1>Current Alerts</h1>
</div>
</body>
</html>
Simple example using the EJS templating, essentially you pass your object to the template at the time of rendering. You can also iterate over data. Same approach can be used for Handlebars or Mustache packages.
var express = require('express');
var path = require('path');
var index = require('./routes/index');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use('/', index);
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
</body>
</html>

Categories

Resources