Issue with Fetch request in Node.js - node.js

i have created a server.js using node and hosted it at "http://localhost:3000".
when vistited "http://localhost:3000" it returns index.html.
in index.html i have attached a javasript file doggos.js(inside public folder) as script src tag, excutes a function onclick of a button in index.html.
when i clicked the button in index.html i can't see the function getting called.
server.js:
const express = require("express");
const path = require("path");
const app = express();
app.get("/", function(req, res) {
res.sendFile(path.join(__dirname, "index.html"));
});
app.listen(3000);
console.log("listening on http://localhost:3000");
index.html:
<!DOCTYPE html>
<html>
<head>
<title> hello world</title>
</head>
<body>
<h1>doggos</h1>
<button id="addNewDog" onclick="">add new dog</button>
<div id="dogs"></div>
<script src="./public/doggos.js"></script>
</body>
</html>
/public/doggos.js:
const DOG_URL = "https://dog.ceo/api/breeds/image/random";
const dogsElement = document.getElementById("dogs")
function addNewDog(){
console.log("fetch dog")
fetch(DOG_URL)
.then(
(response)=>response.json()
)
.then(
(processedResp)=>{
const img = document.createElement("img");
img.src = processedResp.message;
img.alt ="cute dog"
dogsElement.appendChild(img)
}
)
}
document.querySelector("#addNewDog").addEventListener("click", addNewDog)
may i know why the function is not getting called ?

Related

Node js, i can't get my browser button to get a list of teams in the json file

I'm new to Node js, and i'm cuurently writing a program to fetch data from a local json file and display in the browser, but nothing happens when i click the button. Not getting errors either. The program runs as follows: 1). node app.js 2.) opens index.html on the server (127.0.0.1:3000) 3.) click the button "Get list of the team". the button has an action = "teams" and the Controller should invoke the action to fetch the teams from the json file. The Controller invokes the Model, then renders the data in the index.htm property called "teamList". Then i expect to see the teams displayed in the browser. Here is my code:
app.js:
const path = require("path");
const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');
const bodyParser = require('body-parser');
const router = require('./routes/router');
const app = express();
app.use(express.urlencoded({extended: false}));
app.use(express.json());
app.use(express.static("public"));
app.set("views" , "views");
app.set("view engine", "hbs");
const host = "127.0.0.1"
const port = 3000
app.use(cors());
app.use(bodyParser.json());
//app.use('/', router);
app.get('/', (req, res) =>{
res.render("index", {
teamsList: ""
})
})
app.get('/add', (req, res) =>{
res.render("post-tal", {
Sum: ""
})
})
app.listen(port, host, () => {
console.log(`The server is running at: http://${host}:${port}`);
});
index.html:
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>WebApp</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">
<style>
.eNavAction {cursor:pointer}
.buttons {margin-top: 20px}
</style>
<script src="js/simple-helper.js"></script>
<script src="../controller/MainController.js"></script>
<script src="apiServer/controller.js"></script>
<script src="apiServer/model/apiServer-model.js"></script>
<script src="apiServer/routes/router.js"></script>
<script>
var Current = {};
const Model = new TeamsModel();
const View = new TeamView();
const ViewTal = new TalView();
const Controller = new MainController();
document.addEventListener('DOMContentLoaded', function() {
// Controller.init();
Helper.onClassClick('eNavAction', Controller.navAction);
});
</script>
</head>
<body>
<nav class="navbar is-link" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="/">
<span style="font-weight:bold; font-size:20px">My Web App</span>
</a>
</div>
<div id="navbar" class="navbar-menu">
<div class="navbar-start">
<a class="eNavAction navbar-item" action ="teams">Teams</a>
<a class="navbar-item" action= "tal" href="http://127.0.0.1:3000/add">Sum</a>
</div>
</div>
</nav>
<div class="section">
<div id="main-container">
<button class="eNavAction navbar-item" action ="teams">Get list of the team</button>
<div id="listContainer">
{{teamsList}}
</div>
</div>
</div>
</body>
</html>
MainController.js:
class MainContainer {
teamList = (req, res) => {
Model.loadTeams()
.then(function (data) {
res.json(data);
//res.send(data);
res.render("index", {
teamList: {data} // A property called teamList to be displayed on the browser
})
})
.catch(error => console.log(error));
}
navAction() {
let action = this.getAttribute('action');
if (action == "teams") {
Controller.teamList();
}else if(action == "tal")
Controller.calculateSum();
}
}
Model.js
class TeamsModel {
async loadTeams() {
try {
const json = await fetch('./json/prov-nodes.json', 'utf8')
.then(function(response){
return response.json();
})
.then(function(data){
console.log(data);
});
}catch (error) {
console.log(error)
}
}
}
I tried to reconstruct your problem. First of all I show that I fixed code and get result:
that code in controller.js (Model.js)
class TeamsModel {
async loadTeams() {
try {
const json = await fetch('/data/prov-nodes.json')
return json.json(); // Important! return must be in loadTeams!
}catch (error) {
console.log(error) // it'll never been shown!
}
}
}
As you can see I used '/data/prov-nodes.json' as path. Yes now I can access to file that I had not before by './json/prov-nodes.json'.
I just add two strings in app.js:
app.use('/js', express.static(__dirname + '/controllers')); // allows an access
app.use('/data', express.static(__dirname + '/json')); // allows an access
so import of scripts looks like:
<script src="/js/MainController.js"></script>
<script src="/js/controller.js"></script>
in index.hbs file I just do:
const Model = new TeamsModel();
const Controller = new MainController();
Controller.teamList()
I renamed MainContainer class to MainController class (just for test)
...
teamList = (req, res) => {
Model.loadTeams()
.then(function (data) {
console.log('DATA', data); // just output to console if success
})
.catch(error => console.log(error));
}
...
I believe that this helps you continue coding!
I'm not sure that I reconstruct your code right (models/controllers), but I have showed you how to read json file in express.
├── app.js
├── controllers - just modules not real controllers :)
│ ├── MainController.js
│ └── controller.js - I think this would be a model, sorry :)
├── json
│ └── prov-nodes.json
├── package-lock.json
├── package.json
└── views
└── index.hbs

Express Javascript file won't including with get method with parameters

I'm trying render the index file with Express Node.js successfully, but if I'm using namespaces with parameter, without parameter render twig file and included own scripts, if I use try with parameter, render ok bu problem with script files path so script files in head in html cannot including while path not correct
for example, without parameter, in html file style.css look like
<link rel="stylesheet" href="style.css"> path http://127.0.0.1:3000/style.css
with parameter, in html file style.css look like <link rel="stylesheet" href="style.css"> path http://127.0.0.1:3000/mynamespace/style.css <--- and this not found!
say browser path not found!
Server.js
const port = 3000;
const express = require('express');
const app = express();
const http = require('http');
const socketIO = require('socket.io');
const server = http.Server(app);
server.listen(this.port, () => {
console.log(`Server running on: http://127.0.0.1:${port}`);
});
const io = socketIO(server);
app.set('view engine', 'twig');
app.set('views', "views");
app.use(express.static('public'));
app.use(express.static('scripts'));
app.use(express.static("styles"));
/// Routing
/**
* This work fine
* Render client.twig
* Including Scripts in head
*/
app.get('/mynamespace', function (req, res, next) {
res.render("client");
});
/**
* This work with error
* Render client.twig
* don't Including Scripts in head
*
*/
app.get('/mynamespace/:id', function (req, res, next) {
res.render("client");
});
io.of("/mynamespace").on('connection',(socket)=>{
socket.on('online_users', (data) => {
console.log(`Online Users ${data}`);
});
});
client.js
let url = `http://127.0.0.1:3000/mynamespace`;
console.log("Url", url);
this.socket = io(url);
this.socket.on("connect", ()=>{
try{
this.socket.emit('welcome', {
message:"Welcome guest"
});
} catch (e) {
alert(e.message);
}
});
client.twig
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" const="text/html;charset=UTF-8"/>
<title>RestoCommend</title>
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="style.css"
</head>
<body>
<h3>Client</h3>
<script src="helper.js"></script>
<script src="client.js"></script>
</body>
</html>
From your code it looks like the style.css file is in the same directory as client.twig which is the views directory. But you have told express that the static directories are public, scripts and styles. There is no instruction for express to know where to serve the css from. Try moving the style.css file into styles directory.
Good luck.
Sounds like you want to serve your static files under a relative path. Try the following:
app.use('/mynamespace', express.static('public'))
app.use('/mynamespace', express.static('scripts'))
app.use('/mynamespace', express.static('styles'))
And also
<link rel="stylesheet" href="mynamespace/style.css" />
My hierarchy of files
I Solved my problem, but not good idea
Server.js
app.get('/mynamespace1', function (req, res, next) {
app.use(express.static('public'));
app.use(express.static('scripts'));
app.use(express.static("styles"));
res.render("client1");
});
one parameter based namespace!
app.get('/mynamespace2/:clientId', function (req, res, next) {
app.use(express.static(path.join( __dirname + "/../", 'public')))
app.use(express.static(path.join( __dirname + "/../", 'scripts')))
app.use(express.static(path.join( __dirname + "/../", 'styles')))
res.render("client2");
});
more as one parameter based namespace!
app.get('/mynamespace3/:roomName/:clientId', function (req, res, next) {
app.use(express.static(path.join( __dirname + "/../", 'public')))
app.use(express.static(path.join( __dirname + "/../", 'scripts')))
app.use(express.static(path.join( __dirname + "/../", 'styles')))
res.render("client3");
});
client1.twig
<link rel="stylesheet" href="style.css">
<script src="helper.js"></script>
<script src="client.js"></script>
Everything normal
client2.twig
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="../style.css">
<script src="../helper.js"></script>
<script src="../client.js"></script>
with one prameter, script paths defined to parent
client3.twig
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="../../style.css">
<script src="../../helper.js"></script>
<script src="../../client.js"></script>
with more prameters, parent folder defined, until number of parameter
My Problem solved, but I don't like it so

Nodejs client button without redirect

I have a nodejs app that acts as a remote control for Cmus music player. It uses a route for each function ie /play /next etc. This works fine, but with each button click I must call res.redirect("index.html") which obviously causes the page to reload. How can I perform this so that each button click is still able to send the command to the server but not reload the page?
server.js
var express = require('express');
var app = express();
var path = require('path');
var exec = require('child_process').exec;
var Commands = require('./commands.js');
var child;
app.use(express.static(__dirname + '/public'));
//Routes
app.get('/', function (req, res){
res.sendFile(path.join(__dirname + '/index.html'));
});
app.get('/play', function(req, res){
// console.log(req);
handleCommand(Commands.PAUSE);
res.redirect("index.html");
});
var server = app.listen(8080, function () {
console.log("Server online");
console.log(commands.NEXT);
});
function handleCommand(command) {
child = exec(command, function (error, stdout, stderr) {
// sys.print('Stdout ' + stdout);
// sys.print('Stderr ' + stderr);
if (error !== null) {
console.log('ERROR: ' + error);
}
})
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cmus Remote</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="client.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body id="body">
<form action="/play">
<input id="play" type="submit" value="⏯">
</form>
</table>
</body>
</html>
Instead of using a form to "submit" the button, you can attach event handlers to the button that will do a POST request without reloading the page. Then, you won't need to send any redirects at all. Since you have JQuery on the page, I'll give an example with JQuery.
Index.html
<button id="play">Play</button>
<!-- Other code -->
<!-- Script or external JS code -->
<script>
$('#play').click(function(){
$.post('/play');
});
</script>

Pug does not replace parameters with values

The docs of Pug say all the parameters will be replaced with values if they have this form: #{parameter_name} This doesn't work for me.
My code:
//Template
doctype html
html(lang="en")
head
title= title
body
h1
Task is #{task_id}
p
task is #{task_id}
company is #{company_id}
//javascript
var express = require('express')
var app = express()
const util = require('util');
app.set('view engine', 'pug')
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.locals.pretty = true
app.get('/task/:company_id/:task_id',function(req,res) {
res.render('task',{task_id: req.query.task_id,company_id: req.query.company_id});
});
app.listen(8080, function () {
console.log('Example app listening on port !')
})
And the output:
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<h1>
<Task>is </Task>
</h1>
<p>
<task>is </task>
<company>is </company>
</p>
</body>
</html>
No variable was interpreted!!! What is wrong here? I am following the docs!!! (I am using latest version, installed yesterday)
Looks like you are refering to the query string instead of parameters in your nodejs
Please change your code to this
res.render('task',{task_id: req.params.task_id,company_id: req.params.company_id});
You need to use params not query

Image file upload with node and express

Hi i am trying to do an image upload with ajax.so this are my files.
//index.html
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>File Upload showing Upload Progress</title>
<style>
* {
font-family: Verdana;
font-size: 12px;
}
</style>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data" id="MyUploadForm">
<input name="ImageFile" id="imageInput" type="file" />
<input type="submit" id="submit-btn" value="Upload" />
<img src="images/ajax-loader.gif" id="loading-img" style="display:none;" alt="Please Wait"/>
</form>
<div id="output"></div>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.1.min.js'></script>
<script type='text/javascript' src='main.js'></script>
</body>
<script type="text/javascript" src="js/jquery.form.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var options = {
target: '#output', // target element(s) to be updated with server response
beforeSubmit: beforeSubmit, // pre-submit callback
resetForm: true // reset the form after successful submit
};
$('#MyUploadForm').submit(function() {
$(this).ajaxSubmit(options); //Ajax Submit form
// return false to prevent standard browser submit and page navigation
return false;
});
});
//function to check file size before uploading.
function beforeSubmit(){
//check whether browser fully supports all File API
if (window.File && window.FileReader && window.FileList && window.Blob)
{
if( !$('#imageInput').val()) //check empty input filed
{
$("#output").html("Are you kidding me?");
return false
}
var fsize = $('#imageInput')[0].files[0].size; //get file size
var ftype = $('#imageInput')[0].files[0].type; // get file type
//allow only valid image file types
switch(ftype)
{
case 'image/png': case 'image/gif': case 'image/jpeg': case 'image/pjpeg':
break;
default:
$("#output").html("<b>"+ftype+"</b> Unsupported file type!");
return false
}
//Allowed file size is less than 1 MB (1048576)
if(fsize>1048576)
{
$("#output").html("<b>"+fsize +"</b> Too big Image file! <br />Please reduce the size of your photo using an image editor.");
return false
}
$('#submit-btn').hide(); //hide submit button
$('#loading-img').show(); //hide submit button
$("#output").html("");
}
else
{
//Output error to older unsupported browsers that doesn't support HTML5 File API
$("#output").html("Please upgrade your browser, because your current browser lacks some new features we need!");
return false;
}
}
</script>
</html>
this is my app.js
var express = require('express'); //Express Web Server
var bodyParser = require('body-parser'); //connects bodyParsing middleware
var formidable = require('formidable');
var path = require('path'); //used for file path
var fs =require('fs-extra'); //File System-needed for renaming file etc
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
/* ==========================================================
bodyParser() required to allow Express to see the uploaded files
============================================================ */
app.use(bodyParser({defer: true}));
app.route('/').get(function(req,res)
{
console.log("Hello world");
res.render('index.html');
res.end('done');
});
app.post('/upload', function(req, res) {
res.send('fileinfo: ' + req.files);
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
But I am getting req.files undefined.Can anybody tell why? can anybody have solution for my scnario.Am i do everything correctly.
Here is a quotation from the express-formidable-demo page:
Currently broken due to unknown bug
But, you may parse request body explicitly:
app.post('/upload', function(req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
console.log(files);
res.send('fileinfo: ' + files);
});
});

Resources