Html datalist option through JavaScript in node js - node.js

I want to pass data from MySQL database in datalist option. My application is written in express js using ejs view. I can't figure out how to pass database values to list in JavaScript and how to pass this list to ejs file.
add.js:
module.exports = {
addProductPage: (req, res) => {
let query = "SELECT shipper_names.Shipper_ID, shipper_names.Shipper_Name FROM shipper_names";
conn.query(query, (err, results) => {
if (err) {
return res.status(500).send(err);
}
res.render('add-product.ejs', {
title: "Add Product",
shipper_names: results[0],
message: ''
});
});
}
}
EJS file:
<!doctype html>
<html lang="en">
<div>
<a class="float-right" href="/" title="Home">Home</a>
</div>
<div class="contnainer">
<% if (message) {%>
<p class="text-container text-danger">
<%= message %>
</p>
<%}%>
<% if (shipper_names) {%>
<form class="add-player-form" action="" method="POST" enctype="multipart/form-data">
<div>
<input type="text" id="shippers_names" list="languageList" />
<!--your input textbox-->
<datalist id="languageList">
<option value=""> </option>
</datalist>
</div>
<button type="submit" class="btn">Add Product</button>
</form>
<% } else { %>
<p class="text center">Product Not Found. Go HereTo Add Product.</p>
<% } %>
</div>
</html>

module.exports = {
addProductPage: (req, res) => {
let query = "SELECT * from shipper_names"
conn.query(query, (err, results) => {
if (err) {
return res.status(500).send(err);
}
res.render('add-product.ejs', {
shipper_names: results
});
});
},
<div>
<input type="text" id="txtAutoComplete" list="names" />
<!--your input textbox-->
<datalist id="names">
<% shipper_names.forEach((shipper_names, index)=>{%>
<option id=<%= shipper_names.Shipper_ID%>>
<%= shipper_names.Shipper_Name%></option>
<%})%>
</datalist>
</div>
this is working

Related

Getting a 404 error on my nodejs webpage (an example webpage being built following a udemy course)

Back again with another development error. This time around i'm getting a 404 error on one of the routes in my nodejs webpage. I've checked for syntax errors everywhere and apparently have none (if you guys spot something I overlooked please do tell me). The routes are registered correctly (at least as far as my understanding of routes in expressjs goes) and the link that should take me to the page (the "a" tag with a class of "btn" in the products.ejs file, line 23) that isn't loading has a correctly spelled route, because of this I am completely bamboozled as to what it could be and need your help!
I'll embed the code I currently have below so you guys can take a look, and if it's not too much to ask please explain to me what went wrong this time.
Thanks to everyone!
p.s.
My terminal isn't throwing any errors from what I could see so I couldn't attach any!
edit-product.ejs file (view):
<%- include('../includes/head.ejs') %>
<link rel="stylesheet" href="/css/forms.css">
<link rel="stylesheet" href="/css/products.css">
</head>
<body>
<%- include('../includes/navigation.ejs') %>
<main>
<form class="product-form" action="/admin/add-product" method="POST">
<div class="form-control">
<label for="title">Title</label>
<input type="text" name="title" id="title">
</div>
<div class="form-control">
<label for="imageUrl">Image Url</label>
<input type="text" name="imageUrl" id="imageUrl">
</div>
<div class="form-control">
<label for="price">Price</label>
<input type="number" name="price" id="price" step="0.01">
</div>
<div class="form-control">
<label for="description">Description</label>
<textarea name="description" id="description" rows="5"></textarea>
</div>
<button class="btn" type="submit"><% if (editing) { %>Update product<% } else { %>Add Product<% } %></button>
</form>
</main>
<%- include('../includes/end.ejs') %>
product.ejs file (view):
<%- include('../includes/head.ejs') %>
<link rel="stylesheet" href="/css/products.css">
</head>
<body>
<%- include('../includes/navigation.ejs') %>
<main>
<% if (prods.length > 0) {%>
<div class="grid">
<div class="card">
<% for (let product of prods) { %>
<article class="product-item">
<header class="card__header">
<h1 class="product__title"> <%= product.title %> </h1>
</header>
<div class="card__image">
<img src="<%= product.imageUrl %>", alt="">
</div>
<div class="card__content">
<h2 class="product__price"> $<%= product.price %> </h2>
<p class="product__description"> <%= product.description %> </p>
</div>
<div class="card__actions">
Edit
<form action="/admin/delete-product" method="POST">
<button class="btn" type="submit"> Delete </button>
</form>
</div>
</article>
<% } %>
</div>
</div>
<% } else { %>
<h1>No Products</h1>
<% } %>
</main>
<%- include('../includes/end.ejs') %>
admin.js file (routes):
const path = require('path');
const express = require('express');
const adminController = require('../controllers/admin');
const router = express.Router();
// /admin/add-product => GET
router.get('/add-product', adminController.getAddProduct);
// /admin/product => GET
router.get('/products',adminController.getProducts);
// /admin/add-product => POST
router.post('/add-product', adminController.postAddProduct);
router.get('/edit-product/:productId', adminController.getEditProduct);
module.exports = router;
product.js file:
const fs = require('fs');
const path = require('path');
const p = path.join(
path.dirname(process.mainModule.filename),
'data',
'products.json'
);
const getProductsFromFile = cb =>{
fs.readFile(p, (err, fileContent) => {
if(err) {
cb([]);
} else{
cb(JSON.parse(fileContent));
}
});
};
module.exports = class Product {
constructor(title, imageUrl, description, price) {
this.title = title;
this.imageUrl = imageUrl;
this.description = description;
this.price = price;
}
save() {
this.id = Math.random().toString();
getProductsFromFile(products => {
products.push(this);
fs.writeFile(p, JSON.stringify(products), (err) => {
console.log(err);
});
});
}
static fetchAll(cb) {
getProductsFromFile(cb);
};
static findById(id, cb) {
getProductsFromFile(products => {
const product = products.find(p => p.id === id);
cb(product);
});
};
};
admin.js file (controller):
const Product = require('../models/product');
exports.getAddProduct = (req, res, next) => {
res.render('admin/edit-product', {
pageTitle: 'Add Product',
path: '/admin/add-product',
editing: false
});
};
exports.postAddProduct = (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
const product = new Product(title, imageUrl, description, price);
product.save();
res.redirect('/');
};
exports.getEditProduct = (req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
return res.redirect('/');
}
const prodId = req.params.productId;
Product.findById(prodId, product => {
if(!product) {
return res.redirect('/');
}
res.render('admin/edit-product', {
pageTitle: 'Edit Product',
path: '/admin/edit-product',
editing: editMode,
product: product
});
});
};
exports.getProducts = (req, res, next) => {
Product.fetchAll(products => {
res.render('admin/products', {
prods: products,
pageTitle: 'Admin Products',
path: 'admin/products'
});
});
};
Upon looking yet again at the videos I found the answer to my problem. Everything in the code is written correctly, the problem relies on the url I was using. The problematic route was "/admin/edit-product" because there isn't a route connecting to that view, instead the route in the code is "/edit-product/:productId". My mistake was that I had to specify manually the url in my browser because I haven't coded it otherwise.

Cannot read property 'contentType' of undefined

I'm creating facebook like social media app using nodejs and ejs. I'm getting error " Cannot read property 'contentType' of undefined". But I get this error on profile.ejs and not on newsfeed.ejs. profile.ejs render photo if there's photo in the post but if I post a post with text only,this "Cannot read property 'contentType' of undefined" error occur.
app.js
app.get("/newsfeed", function(req, res){
if(req.isAuthenticated()){
Post.find({}, function(err, foundItem){
if(err){
console.log(err);
} else {
const loggedUser = req.user;
res.render("newsfeed", {posts: foundItem, loggedUser: loggedUser, foundUser: "undefined"});
}
}).sort({date: -1});
} else {
res.redirect("/login");
}
});
app.get("/profile/:userProfile", function (req, res) {
const userId = req.params.userProfile;
const loggedUser = req.user
if(req.isAuthenticated){
User.findById(userId, function(err, foundUser){
if(err){
console.log(err);
} else {
res.render("profile", {foundUser: foundUser, loggedUser:loggedUser});
}
}).sort({date: -1});
}
})
newsfeed.ejs
<% posts.forEach( function(post) { %>
<div class="post">
<!-- Post contents -->
<%= post.name %>
<p class="date"><%= post.date %></p>
<p class="content"><%= post.content %></p>
<% if(post.img != "undefined") { %>
<div class="mediaFiles">
<div class="imageOverlay"><i class="fas fa-times"></i></div>
<img src="data:image/<%=post.img.contentType%>;base64,
<%=post.img.data%>" class="image" onerror="this.style.display='none'">
</div>
<% } %>
<hr>
<% }); %>
profile.ejs
<% foundUser.post.forEach( function(post) { %>
<div class="post">
<!-- Post contents -->
<%= post.name %>
<p class="date"><%= post.date %></p>
<p class="content"><%= post.content %></p>
<% if(post.img != "undefined" || post.img != null || post.img != "") { %>
<div class="mediaFiles">
<div class="imageOverlay"><i class="fas fa-times"></i></div>
<img src="data:image/<%=post.img.contentType%>;base64,
<%=post.img.data%>" class="image" onerror="this.style.display='none'">
</div>
<% } else { %>
<div class="imageOverlay"><i class="fas fa-times"></i></div>
<img src="#" class="image" onerror="this.style.display='none'">
</div>
<% } %>

Pass data from Vue front end to Node/Express backend

I want a user to be able to enter a city into a text input at the '/' route. Once that is submitted, id like to redirect to '/result' and show the info. The only way I can get '/result' to show what I want is if I hard code a city in the back end. How do I eliminate this?
GET request
app.get('/result', (req, res) => {
let city = 'Portland';
let url = `${process.env.BASEURL}${city}&units=imperial&APPID=${process.env.API_KEY}`;
axios.get(url)
.then(response => { res.json(response.data) })
.catch(error => {
return res.status(500).json({
success: false,
message: error.message
})
});
});
Service file that passes data from backend API
import axios from 'axios';
const url = "http://localhost:5000/result";
class WeatherService {
static getWeather() {
return new Promise((resolve, reject) => {
axios.get(url).then((res) => {
try {
resolve(res.data);
} catch (error) {
reject(error);
}
})
})
}
}
export default WeatherService;
Front end
<template>
<div>
<p class="error" v-if="error">{{ error }}</p>
<i class="fa fa-times close-icon none"></i>
<main>
<div class="location none">
<div class="city">{{ weather.name }}</div>
<div class="long-lat">{{ weather.coord.lon }}, {{ weather.coord.lat }}</div>
<div class="date">-, -:- pm</div>
</div>
<div class="main-content none">
<div class="tempIcon">
<div class="condition-icon"></div>
<div class="temp">{{ weather.main.temp }}<span>°</span></div>
</div>
<div class="weather">{{ weather.weather[0].main }}</div>
<div class="hi-low">{{ weather.main.temp_max }}° / {{ weather.main.temp_minl }}° <span></span>Feels like {{ weather.main.feels_like }}°</div>
</div>
</main>
<section class="details">
<div class="humidity none">
<i class="fa fa-tint"></i>
<h5>Humidity</h5>
<p class="humidity-value">{{ weather.main.humidity }}%</p>
</div>
<div class="pressure none">
<i class="fa fa-tachometer"></i>
<h5>Pressure</h5>
<p class="pressure-value">{{ weather.main.pressure }} hPa</p>
</div>
<div class="wind none">
<i class="fa fa-wind"></i>
<h5>Wind</h5>
<p class="wind-value">{{ weather.wind.speed }} mph</p>
</div>
</section>
</div>
</template>
<script>
import WeatherService from '../WeatherService';
export default {
name: 'Result',
data(){
return {
weather: [],
error: ''
}
},
async created() {
try {
this.weather = await WeatherService.getWeather();
} catch (error) {
this.error = error.message;
console.log(error);
}
}
}
</script>
You could pass some parameters like this
axios.get('/result', {
params: {
city: 'Portland'
}
})
This, of course, will need to be forwarded to your function to make it dynamic.
You can also use some headers or make a POST request rather than a GET. Not sure of the real differences between all those solutions tho.

Mongoose doesnt save multiline string

When i try to put a multiline string into a mongoose database it doesnt want to work. It just saves one line of the string.
Logging content to console:
Website result:
EJS Code
<% posts.forEach(function(post){ %>
<div class="card mb-2" style="width: 100%;">
<div class="card-body">
<% if(user.admin == true || user.id == post.authorid){ %>
<form action="/deletepost/<%= post.id %>" method="post">
<button type="submit" class="btn btn-sm btn-danger btn-block">Delete</button>
</form>
<br>
<% } %>
<h5 class="card-title"><%= post.authorname %></h5>
<h6 class="card-subtitle mb-2 text-muted"><%= post.date %></h6>
<hr>
<p class="card-text"><%= post.content %></p>
</div>
</div>
<% }); %>
Mongoose model:
const PostSchema = new mongoose.Schema({
content: {
type: String
}
})
How i save to database:
var newPost = {content, authorid, authorname};
Post.create(newPost, function(err, newlyCreated){
if(err){
console.log(err);
} else {
res.redirect("/app")
}
});
I use express & ejs if that matters.

JSON value returning as 'undefined' despite being well formed in nodeJS and SQLite3

I am trying to do multiple async requests to a SQLite database and then render them in a web page using node/express and ejs templating. I am able to retrieve the data in JSON from the database request but when pushing it to another JSON object, it is returning as undefined.
app.js
//Set up web server
const express = require('express');
const app = express();
var dashboard = require('./dashboard.js');
var async = require('async');
//Set view engine and allow access to public/css
app.set('view engine', 'ejs');
app.use(express.static('public/css'));
//Start server
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
})
//Connect to database
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('fishtank.db');
//Home page
app.get('/', function(req, res) {
//Temps variables
var currentAmbientTemp = '18.2';
var lightStatus = 'OFF';
var airPumpStatus = 'OFF';
//Get temps from database
var tempHistoryQuery = "SELECT * FROM watertemp LIMIT 5";
var currentWaterTempQuery = "SELECT temp FROM watertemp LIMIT 1";
async.series({
tempHistory: function(callback){
db.all(tempHistoryQuery, (err, results)=> {
callback(results);
})
},
currentWaterTemp: function(callback){
db.all(currentWaterTempQuery, (err, results)=> {
callback(results);
})
}
},function(err, results) {
res.render('index', {
tempHistory: results['tempHistory'],
currentWaterTemp: results['currentWaterTemp'],
currentAmbientTemp: currentAmbientTemp,
lightStatus: lightStatus,
airPumpStatus: airPumpStatus
})
console.log(results);
});
});
index.ejs
<!-- views/pages/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head><% include partials/head %></head>
<body class="container">
<!--HEADER-->
<header><% include partials/header %></header>
<!--MAIN BODY-->
<main>
<!--OVERVIEW SECTION-->
<div class="row">
<div class="col-md-12 dash-section">
<h3>Overview</h3>
</div>
<!--WATER TEMP-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">WATER TEMP</div>
<div class="panel-body"><%= currentWaterTemp %>°C</div>
</div>
</div>
<!--AMBIENT TEMP-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">AMBIENT TEMP</div>
<div class="panel-body"><%= currentAmbientTemp %>°C</div>
</div>
</div>
<!--LIGHT STATUS-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">LIGHT STATUS</div>
<div class="panel-body"><%= lightStatus %></div>
</div>
</div>
<!--AIR PUMP STATUS-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">AIR PUMP STATUS</div>
<div class="panel-body"><%= airPumpStatus %></div>
</div>
</div>
</div>
<!--DETAILS SECTION-->
<div class="row">
<div class="col-md-12 dash-section">
<h3>Details</h3>
</div>
<!--WATER TEMP DETAILS-->
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading"><strong>WATER TEMP HISTORY</strong></div>
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">Date/Time</th>
<th scope="col">Temp</th>
</tr>
</thead>
<tbody>
<% for(var i=0; i < tempHistory.length; i++) { %>
<tr>
<td><%= tempHistory[i].datetime %></td>
<td><%= tempHistory[i].temp %></td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
<!--AMBIENT TEMP DETAILS-->
<div class="col-md-4 ml-auto">
Ambient Temp Table
</div>
<!--TBC DETAILS-->
<div class="col-md-4 ml-auto">
TBC
</div>
</div> <!--End of row-->
</main>
<!--FOOTER-->
<footer><% include partials/footer %></footer>
</body>
</html>
console.log(results); is giving me:
{ tempHistory: undefined }
But when logging it from within the callback function, I get:
[ { id: 1, datetime: '2018-02-24 12:56:02.123456', temp: 29.5 },
{ id: 2, datetime: '2018-02-24 13:56:02.123456', temp: 28.5 },
{ id: 3, datetime: '2018-02-24 14:56:02.123456', temp: 26.5 },
{ id: 4, datetime: '2018-02-24 15:56:02.123456', temp: 26.7 },
{ id: 5, datetime: '2018-02-24 16:56:02.123456', temp: 25.9 } ]
Any help would be greatly appreciated.
EDIT
I suspect now that you are calling back in the wrong way. The first parameter of callback should be an error and the result should be the second parameter. See below:
async.series({
tempHistory: function (callback) {
db.all(tempHistoryQuery, (err, results)=> {
callback(err, results);
})
},
currentWaterTemp: function (callback) {
db.all(currentWaterTempQuery, (err, results) => {
callback(err, results);
})
}
},function (err, results) {
// Don't forget to check for error here.
});
Which can be simplified to:
async.series({
tempHistory: cb => db.all(tempHistoryQuery, cb),
currentWaterTemp: cb => db.all(currentWaterTempQuery, cb)
}, (err, results) => {
// ..
});
For reference see the example code of .series

Resources