Node, Ejs, Express, passing variables to partial views. issues with re-using the same code in the express routes. Need to condense code - node.js

I am a newbie to node, express and ejs. I am creating a blog website project. I want to make use of EJS partials to stop repeating elements of code on my website. The simplified structure is
Blog
--js
--sql-helpers.js
--routes
--routes.js
--views
--homepage.ejs
--aboutpage.ejs
--header(Partial).ejs
The partial header ejs file is to be used on all webpages as it displays the title and author of the blog.
Here is a snippet of code from the routes file:
routes.js
router.get('/homepage', (req, res) => {
const sql = 'SELECT * FROM authors';
global.db.all(sql,[], function(err,rows){
const blogInfo = rows[0];
const params = {
authorName:blogInfo.author_name,
authorBlogTitle:blogInfo.authors_blog_title,
authorSubtitle:blogInfo.authors_blog_subtitle
};
res.render('homepage', params);
});
});
router.get('/aboutpage', (req,res) => {
const sql = 'SELECT * FROM authors';
global.db.all(sql,[], function(err,rows){
const blogInfo = rows[0];
const params = {
authorName:blogInfo.author_name,
authorBlogTitle:blogInfo.authors_blog_title,
authorSubtitle:blogInfo.authors_blog_subtitle
};
res.render('aboutpage', params);
});
});
As you can see I am having to re-use the same code in each of the routes to fill the variables in the header(partial).ejs file.
The homepage.ejs file code is as follows:
<!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>Home Page</title>
</head>
<body>
<%- include('header(Partial)') %>
</body>
</html>
The header(partial).ejs file looks like this:
<header>
<section>
<h1 ><strong><%= authorBlogTitle %></strong></h1>
<span><%= authorSubtitle %></span>
<p ><small><%= authorName %></small></p>
</section>
</header>
To try and stop re-peating the same code i created a sql-helpers js file. as follows
const blogheader = function(callback){
const sql = 'SELECT * FROM authors';
global.db.all(sql,[], function(err,rows){
const blogInfo = rows[0];
const params = {
authorName:blogInfo.author_name,
authorBlogTitle:blogInfo.authors_blog_title,
authorSubtitle:blogInfo.authors_blog_subtitle
};
callback(params);
});
}
module.exports = {blogheader};
updated routes.js file:
const helpers = require("../public/js/sql_scripts");
router.get('/settings', (req,res) => {
let bloginfo = helpers.blogheader()
res.render('settings', blogheader);
});
My problems is I when i try and use this sql helper function in the routes I am getting a undefined value. Is this the best way to do it? How can wrap up my sql query so i dont have to repeat the same code in the routes? Is there a better way to use ejs partials?
I have been stuck on this issue for a number of days, searching the internet for an answer but I just havent found anything that helps me.

Related

routing a webpage error, nodejs and expressjs

I am trying to route directly to the html file using express.js, getting an unknown error, being new to express.js, I couldn't get how to resolve this one:-
here is the js code :-
const express = require('express');
const path = require();
const app = express();
const port=process.env.PORT || 8000;
// public static path
const static_path = path.join(__dirname,"../public");
app.use(express.static(static_path));
app.get("",(req,res)=>{
res.send("welcome to this main page");
})
app.get("/about",(req,res)=>{
res.send("welcome to this about page");
})
app.get("/weather",(req,res)=>{
res.send("welcome to this weather page");
})
app.get("*",(req,res)=>{
res.send("404 Error page oops");
})
app.listen(port,()=>{
console.log(`listening to the port ${port}`);
})
static web page:-
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>Weather App</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>Welcome to the static web</h1>
</body>
</html>
getting this error:-
internal/validators.js:124
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
^
TypeError [ERR_INVALID_ARG_TYPE]: The "id" argument must be of type string. Received undefined
ok, I was using "type nul > filename" command for creating new files in attached folders. When I used directly the VSCode feature of creating files, it's working fine now,... don't know why, but I think that old command might have expired, tell me if I am wrong, but I just solved my issue...

How do I get HTML-linked JS files to use Require?

I am an express newbie, and I am trying to get a static HTML page to read details from a file in Express.
Initially I had a static HTML page where users could register where they were based on a particular day (as we are now rather flexible with working arrangements). However, it became apparent that I needed to store the current situation somewhere each time someone updated their details (and retrieve it when someone else signs on), so I did some investigating and came up with Node and Express.
I have an HTML file in the public directory, and it links to a JS file where I want to do a "fs" read.
app.js
app.use(express.static(path.join(__dirname, 'public')));
var steveRouter = require('./routes/steve');
app.use('/steve', steveRouter);
routes/steve.js
var express = require('express');
var path = require('path');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.sendFile(path.resolve(__dirname, '../public', 'steve.html'))
});
module.exports = router;
public/steve.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World : title</title>
<script src="steve.js"></script>
</head>
<body onLoad="loadUp()">
<h3>small-ish heading</h3>
</body>
</html>
public/steveHtml.js
const fs = require('fs');
function loadUp() {
alert("Ciao");
let rawdata = fs.readFileSync('student.json');
let student = JSON.parse(rawdata);
console.log(student);
alert(student.name);
}
The server starts ok, but the browser shows the message "Uncaught ReferenceError: require is not defined at steveHtml.js:1"
This is probably the wrong way of doing it, but I would love to know :
how do I get the "called" JS file to recognise the require command?
is there a better/simpler/easier way of accomplishing what I want?

How to upload and display a file in Node.js?

I'm new to Node and have some problems with uploading files. I'm trying to to upload images (both jpg and png) and text files in text/plain and then display them at the post-route ('/upload)'. I've tried both multer and formidable but cannot get it right. Would really appreciate some help.
I tried all different kinds of events and callbacks, but I'm missing some crucial steps. Here is the html:
<!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>Testform</title>
</head>
<body>
<form method="post" enctype="multipart/form-data"
action="/upload">
<div>
<input type="file" name="file" size="35">
</div>
<button type="submit" value="Click me" name="submit-btn">Click me</button>
</form>
</body>
</html>
And here is the server code:
const formidable = require('formidable')
const express = require('express')
const path = require('path')
const app = express()
app.get('/', (req, res) => {
res.sendFile(path.resolve('views', 'index.html'))
})
app.post('/upload', (req, res) => {
const form = new formidable.IncomingForm()
form.uploadDir = __dirname + '/uploads/'
form.parse(req)
form.on('fileBegin', (name, file) => {
file.path = form.uploadDir + file.name
res.write(`<img src="./uploads/${file.name}">`)
res.end()
})
})
app.listen(3000)
My root folder contains app.js, views/index.html, and a directory called uploads.
The code is my test case for image uploads. When I run the program a file with the correct name and content get uploaded into the directory './uploads'. However, I cannot see the uploaded image in the response of the post request ('/upload'). Would be great if anyone could help me with this and also for other text files (text/plain). Cheers!
In the response of the request you can send values, so something like res.end(value here) works!

Reading a part of file in NodeJs

Goal: To read a part/particular section of file using NodeJS.
My code:
fs = require('fs')
fs.readFile('/test/index.html', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
console.log(data);
});
Problem: This is reading whole file. And i want to read the text between body tag of html file.
Output in console:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h2>Card</h2>
<div class="card">
<img src="https://www.w3schools.com/howto/img_avatar.png" alt="Avatar" style="width:100%">
<div class="container">
<h4><b>John Doe</b></h4>
<p>Engineer</p>
</div>
</div>
</body>
</html>
You need parse the text, and extract the desired part.
using Regex its possible but problematic.
for parse html its recommended use cheerio (see example), in your case (select by node) you can also use "simple" xml reader as xml2js.
using cheerio :
const cheerio = require('cheerio')
fs = require('fs')
fs.readFile('/test/index.html', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
const $ = cheerio.load(data);
console.log($('body'));
});

How to share common function between server and client using node.js

Following are the structure of my application
Inside prototype.js file i have following code:
(function(exports) {
exports.foo = function() {
return 'bar';
};
})((typeof process === 'undefined' || !process.versions) ? window.common = window.common || {} : exports);
app.js contains
var express = require('express'),app = express(),server = require('http').createServer(app),io = require('socket.io').listen(server),port = 3000,path = require('path');
var common = require('common/prototype');
console.log(common.foo());
// listening to port...
server.listen(port);
//Object to save clients data
var users = [];
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function (req, res) {
res.sendfile('/public/index.html');
});
index.html contains
<!doctype html>
<html lang="en">
<head>
<title>Socket.io Demo</title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script src="/common/prototype.js"></script>
<script>
alert(window.common.foo()); //This line will gives me an error TypeError: window.common is undefined
</script>
</body>
</html>
Now i would like to print
Hello, I am bar from server and client as well.
Now i am able to print from server side using following line
var common = require('common/prototype');
console.log(common.foo());
But could not able to show alert on client side. could you please help me to find the root cause for the issue.
The root cause is that when you do <script src="/common/prototype.js"></script> in your HTML the file won't be fetched because the Express static middleware is only looking for files under your public folder.
A quick way to test this is to copy your prototype.js to your javascript folder inside public. Then update your script tag to reference the file as follows <script src="/javascripts/prototype.js"></script>
The thing to remember is that the JavaScript files that live under node_modules are not automatically available to the browser.

Resources