I have server side code which serves up a pug file, the pug file has variables parsed to it when rendered by my server side code.
I would like to be able to update that variable in pug when a check box is checked / unchecked.
my server side code:
// load the express module
const express = require('express');
const simpleVarDisplaySite = 'simpleVarDisplay.pug';
const app = express();
app.use(express.urlencoded({extended: false}))
app.use(express.static(__dirname+'/static'));
// simpleVarDisplaySite page
app.get('/', function (req, res) {
console.log(req.url);
let myHeading = 'Simple Pug Page';
let simpleObject = {
'date': {
'day': 'time'
}
}
res.render(simpleVarDisplaySite, {
heading: myHeading,
pugObject: simpleObject,
});
})
app.listen(8082)
my pug file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Pug</title>
<link rel="stylesheet" href="/styles/MainStyling.css">
<script src="/scripts/pugVarUpdater.js"></script>
</head>
<body>
<form method="POST">
<div>
<header>
<h1 class="HeaderEl" id="heading">#{ heading }</h1>
</header>
<div>
<input type="checkbox" id="simpleCheckBox" onchange="JavaScript:updatePugVarFunc()">
</div>
<br>
each valueDict, date in pugObject
<div>
<div>
<span>#{date}</span>
</div>
<br>
each time, day in valueDict
<div>
<span>#{day}</span>
</div>
<div>
<span>#{time}</span>
</div>
</div>
</div>
</form>
</body>
</html>
my client-side js when checkbox is checked / unchecked:
function updatePugVarFunc() {
const simpleVarDisplaySite = 'simpleVarDisplay.pug';
let newSimpleObject = {
'new_date': {
'new_day': 'new_time'
}
}
alert(newSimpleObject)
let myNewHeading = 'My New Simple Heading'
alert(myNewHeading)
document.body.innerHTML = simpleVarDisplaySite({
heading: myNewHeading,
pugObject: newSimpleObject,
});
}
I would like to have pug variable: pugObject updated when the checkbox is checked / unchecked onChange event, and see the updates in my browser, which I have tried with:
document.body.innerHTML = simpleVarDisplaySite({
heading: myNewHeading,
pugObject: newSimpleObject,
});
But that does not work.
I know that client-side is handled rather differently from server-side, but I am soo hoping that there is a solution to my specific problem.
Please note that I am a nood with javascript and pug, and I am very open to any and all suggestions to better achieve my goal.
My File structure:
server.js
views
simpleVarDisplay.pug
static
scripts
pugVarUpdater.js
PS:
I have had a look at: use client-side js variable in pug
And that did not help me.
Your assistance and guidance is much appreciated.
Related
Basically I have a .json file, and I want to make a html page that someone can fill out a form, and the information in the form will change variables in the JSON file.
Example:
The json file (for example):
{“title”: “(variable)”}
then when the html form is submitted it will read (variable) as what was entered into the form.
It depends on what you have on the backend (Node, python, etc)
Welcome to Stackoverflow, seeing that you have NodeJS, you may want to establish some sort of communication from your back end to front end. Let's say you're using websockets. Here is how information would be passed:
userData.json:
{
name: "Mishra",
age: 89
}
server.js:
const app = express()
const server = app.listen(3000) // setup express server
const io = require('socket.io').listen(server); // using websockets
let userData = require('./userData.json');
// on socket connection event
io.on('connection', (socket) => {
socket.on('updateName', name => { // when updateName is called
userData.name = name // set JSON var to new name
})
}
// method to save JSON file goes here
myForm.html:
<head>
<script type="text/javascript" src="your/path/to/socket.io.js"></script>
<script>
var socket = io();
</script>
</head>
<body>
Set name:
<input type="text" id="nameField" name="fname"><br>
<input type="submit" value="Submit" id="submit">
<script>
document.getElementById("submit").onclick = () =>{
socket.emit("updateName", document.getElementById("nameField").value)
}
</script>
</body>
This is my function to fetch data:
let a = showbtn.addEventListener('click',function(){
list.innerHTML='';
fetch('http://localhost:3000/products')
.then ( response =>response.json())
.then( data => {
data.forEach( product => {
let li =document.createElement('li');
li.textContent=` ${product.id} - ${product.name} - $ ${product.price} `;
list.appendChild(li);
});
})
})
My App.js looks like this:
let express=require('express');
app=express();
//after completing index.html we set index.html as a home page like this by introducing public client folder:
app.use(express.static('public'));
productsArray=[];
//every products must have an id number:
let id=1;
app.use(express.json());
//showing all products:
app.get('/products',(req,res)=>{
res.send(productsArray);
})
//creating ptoducts(posts):
app.post('/products',(req,res)=>{
let newProduct=req.body;
newProduct.id=id;
id++;
productsArray.push(newProduct);
res.send('new product created by newProduct=req.body and added to array by push method: Array.push(newProduct)')
})
This is my HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>shop</title>
</head>
<body>
<h1>shop</h1>
<h2>show all products</h2>
<button class="show-products">show</button>
<!-- //everyl ist item is a separate product -->
<ul class="product-list"></ul>
<!-- //.................................................................... -->
<h2>add product</h2>
<form class="add-product-form">
<p>
<label for="add-product-name">
product:
</label>
<input id="add-product-name" type="text" >
</p>
<p>
<label for="add-product-price">
price:
</label>
<input id="add-product-price" type="text" >
</p>
<button>add</button>
</form>
<script src="js/script.js"></script>
</body>
</html>
The problem is that when i open chrome on localhost:3000 and type something in the field of products and price after that i click show button but i get this result something like this:
1 - undefined - $ undefined
the first one is it's id and the second is product name but is undefined and price as well. I think something is wrong with value but i can't solve this problem.
Thank you in advance.
When handling POST bodies in express you need to user body-parser
http://expressjs.com/en/resources/middleware/body-parser.html
npm install body-parser
var bodyParser = require('body-parser')
Code from the docs
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
in the js file remove the semicolon and replace it with comma
I am trying to serve html files from server without using template engines. Please find the below script for starting the server.
// script.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(express.static(__dirname));
app.get("/", (req, res) => {
res.set("Content-Type", "text/html");
const f = require("./templates")();
console.log(f);
res.send(f);
});
app.listen(3103, () => console.log("hi"));
// template.js
const fs = require("fs");
const html = fs.readFileSync(__dirname + "/temp.html", "utf8");
module.exports = (variables) => {
return html;
};
Following is my html file:
<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>
<script src="./script.js"></script> <!-- The click function was served in a different file -->
</head>
<body>
<p>Home Page</p>
<input type="button" value="Click Me" id="btn" onclick="click()">
<script>
console.log("hi");
function click(){ console.log("_Button clicked"); }
//document.getElementById("btn").addEventListener("click", () => {
//console.log("Button Clicked");
//});
</script>
</body>
</html>
I tried the following without any success:
I included the click() inline in the button element, and the function was declared in script tag in the same html file. This did not work.
I included the fromScript function in script.js file and served that file as static content. This did not work as expected.
Then I used addEventListener to bind the click event to input element. Now whenever I click the button, "Button Clicked" message is printed twice.
What is the correct/best practice for binding dom events to the elements?
Edit
Thanks for the answer Thijs Kramer. But the problem is due to the function name.
If I name the function as click it is not working. But if I rename it to fromScript it is working.
Should we not use "click" for function name?
Your problem has nothing to do with express :)
The best practice for binding click events is for example the following:
<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>
<p>Home Page</p>
<input type="button" value="Click Me" id="btn">
<script>
const button = document.getElementById("btn");
button.addEventListener("click", () => {
console.log("Button Clicked");
});
</script>
</body>
</html>
Edit: I think I know what you mean:
If you rename the function fromScript to click, you obviously have to change the value of the onclick attribute as well:
<input type="button" onclick="click()" />
The reason for your naming problem is that the HTMLElement API (which all html elements inherit from) has a click property. It is a function meant to be used to programmatically trigger a click event on the element.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
To avoid confusion and unpredictable behaviour, always make sure to name your variables and functions unambigously with regard to inherited and built-in properties from the prototype chain.
The below code should work fine:
// script.js
const express = require("express");
// const bodyParser = require("body-parser");
const app = express();
app.use(express.static(__dirname));
app.listen(3103, () => console.log("hi"));
then node script.js and try to access it by going to http://localhost:3103/temp.html
?
I'm trying to render this html document ./tagslegend.html with npm package wkhtmltox:
<!doctype html>
<html>
<head>
<style>
.cmn {
font-family: 'WenQuanYi Micro Hei';
}
</style>
</head>
<body>
<dl>
<dt class="cmn">中文</dt><dd>In mandarin language.</dd>
</dl>
</body>
</html>
Here's the javascript:
const express = require('express');
const fs = require('fs');
const wkhtmltox = require('wkhtmltox');
const app = express();
const converter = new wkhtmltox();
app.get('/tagslegend.png', (request, response) => {
response.status(200).type('png');
converter.image(fs.createReadStream('tagslegend.html'), { format: "png" }).pipe(response);
});
var listener = app.listen(process.env.PORT, function () {
console.log('App listening on port ' + listener.address().port);
});
I expect it to render like my browser would render that same html:
But am instead getting a png like this:
How can I fix this and make it render like the first image?
I have that font installed on the server:
$ fc-list | grep 'Wen'
/app/.fonts/WenQuanYi Micro Hei.ttf: WenQuanYi Micro Hei,文泉驛微米黑,文泉驿微米黑:style=Regular
This looks like an character encoding problem. It seems as if fs.createReadStream() is reading your HTML as ISO-8859-1, when it really should be reading it as UTF-8 — which is odd, since UTF-8 is the default encoding.
I'd make sure tagslegend.html is properly saved as a UTF-8 file. It couldn't hurt to explicitly declare:
<meta charset="utf-8">
...in the <head> section of your HTML as well.
I have the following express app which just renders the sample.ejs page. On that page when I press the button the attached script changes the div text to
"THIS IS FROM J QUERY. I want the same thing to happen but I want the data to be coming from a database. In my express app if I try to use res.render(); every time I click the button then it reloads the page which I don't want. So is there a way to achieve this without reloading page and only update part of page?
I have searched stack overflow and the web but can't get an appropriate answer or maybe I just am unable to understand. I know this is a very basic thing to ask.
APP.js
var express = require('express');
var app = express();
app.use(express.static('public'));
app.use(express.static('./src/views'));
app.set('views', './src/views');
app.set('view engine' , 'ejs');
app.listen(3000 , (err)=>{console.log('Listening')});
app.get('/' , function(req , res) {
res.render('sample' , {result_from_database: res.body} );
});
sample.ejs
<!doctype html>
<html lang="en">
<head>
<title>Sample HTML File</title>
</head>
<body>
<div id="holder">
WELCOME
</div>
<form>
<button type="button" id="HButton"> HELLO </button>
</form>
</body>
<script>
$(document).ready(function () {
var form = $("#holder");
$("#HButton").on("click", function () {
form.html("THIS IS FROM J QUERY");
});
});
</script>
<script src="/lib/jquery/dist/jquery.js"></script>
</html>
Now this is what I want to do
<!doctype html>
<html lang="en">
<head>
<title>Sample HTML File</title>
</head>
<body>
<div id="holder">
<%= result_from_database %>
</div>
<form>
<button type="button" id="HButton"> HELLO </button>
</form>
</body>
<script>
$(document).ready(function () {
var my_div = $("#holder");
$("#HButton").on("click", function () {
/* Tell app.js that I clicked a button and then app.js
query the database and using ejs or something else update the
my_div inner html with the database result without
reloading page */
});
});
</script>
<script src="/lib/jquery/dist/jquery.js"></script>
</html>
NOTE: I'm not asking how to query the database
-Thanks
You have to define and endpoint in your back end that return the information you want to display:
app.js
var express = require('express');
var app = express();
app.use(express.static('public'));
app.use(express.static('./src/views'));
app.set('views', './src/views');
app.set('view engine' , 'ejs');
app.listen(3000 , (err)=>{console.log('Listening')});
app.get('/' , function(req , res) {
res.render('sample' , {result_from_database: res.body} );
});
app.get('/api/books', function(req, res) {
res.json({
message: 'Your database information'
});
});
then on your front end you need to make a call to api endpoint like:
sample.ejs
<script>
$(document).ready(function () {
var my_div = $("#holder");
$("#HButton").on("click", function () {
$.ajax({
url: "/api/books"
})
.done(function( data ) {
console.log( "Sample of data:", data );
$('#holder').html(data.message);
});
});
});
</script>
You can find more information on ajax call with jquery here.
However i would suggest you to use any framework like angular or react to make it easier to render the data in your html, otherwise you will have to write a lot of code using jquery.