Handlebars app.js file is not rendering array information properly locally - javascript

My app.js file looks like this:
const express = require('express');
const exphbs = require('express-handlebars');
const app = express();
app.engine('hbs', exphbs.engine({
defaultLayout: 'main',
extname: '.hbs'
}));
app.set('view engine', 'hbs');
app.get('/', (req, res) => {
res.render('home');
});
app.listen(3000, () => {
console.log('The web server has started on port 3000');
});
app.get('/', function (req, res) {
res.render('home', {
post: {
author: 'John Smith',
image: 'https://picsum.photos/500/500',
comments: []
}
});
});
My home.hbs file looks like this:
<nav class="navbar navbar-dark bg-dark">
<a class="navbar-brand" href="#">Book Face</a>
</nav>
<div class="posts">
<div class="row justify-content-center">
<div class="col-lg-7" style="margin-top: 50px;">
<div class="card">
<img src="{{post.image}}"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Posted by {{post.author}}</h5>
<ul class="list-group">
<li class="list-group-item">This is suppose to be a comment</li>
<li class="list-group-item">This is suppose to be a comment</li>
</ul>
</div>
</div>
</div>
</div>
</div>
And finally my main.hbs file looks like this:
<html lang="en">
<head>
<!-- <meta> tags> -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<title>Book Face</title>
</head>
<body>
<div class="container">
{{{body}}}
</div>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>
</html>
When I run it locally, the html is rendering but the dynamic content from the array is not ie. {{post.image}} and {{post.author}} (in the post array in my app.js file). Did I do something incorrectly with the setup of my app.js file? I'm not getting any errors in the console.log.

Related

EJS Template not rendering data while JSON object is present

I have an issue rendering data in an EJS-template. The Object with data is present on the page but when I try to show a specific part of the data it won't render (like recept.title).
Router
router.get("/:slug", function(req, res) {
Recept.find({ slug: req.params.slug})
.exec(function(err, foundRecept) {
if(err || !foundRecept) {
req.flash("error", "Recept niet gevonden");
res.redirect("back");
} else {
res.render("recepten/recept", { recept: foundRecept });
}
});
});
When I render the whole object it will render (as shown below).
HTML File
<div class="row justify-content-center">
<div class="col-md-9">
<div class="card-img-top">
//this doesn't render
<img
class="card-img-top"
src="<%= recept.image %>"
alt="<%= recept.title %>"
/>
</div>
<div class="card-title">
<h1 class="h3"><%= recept.title %></h1>
<p>
//this will render the JSON object
<%= recept %>
</p>
</div>
</div>
</div>
Many thanks in advance.
Regards Jason
Sample Code:
index.js
const express = require("express")
const path=require("path");
const app = express()
app.set('views', path.join(__dirname, '/public'));
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
// being rendered res.render()
const port = 3000
app.get('/', (req, res) => {
var foundRecept=[{"title":"mango"},{"title":"apple"}]
res.render(__dirname + "/public/" + "index.html", { recept: foundRecept });
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
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>
<div class="row justify-content-center">
<div class="col-md-9">
<div class="card-title">
<% for(var i=0; i < recept.length; i++) { %>
<h1 class="h3"><%= recept[i].title %></h1>
<% } %>
</div>
</div>
</div>
</body>
</html>

How to use and retrieve Get/Post Request variables with NodeJS and EJS

I'm currently using NodeJs/Express and EJS for my web application. My goal was to build a simple page, with an input field, for testing XSS attacks. I'm not too experienced with building server-side applications. I was wondering how to send/retrieve the inputs from my text field.
And how do I add a CSS file?
// app.js
var express = require("express");
var path = require("path");
var routes = require("./routes"); // defines routes
var app = express();
app.set("port", process.env.PORT || 3000); // defines port
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
app.use(express.urlencoded({ extended: false}));
app.use(routes);
app.listen(app.get("port"), function() {
console.log("Server started on port: " + app.get("port"));
});
// routes.js
var express = require("express");
var router = express.Router();
router.get('/', function(req, res, next) {
console.log("Hello I'm on the start page here.");
res.render('index', {page:'Home', menuId:'home'});
});
router.get('/about', function(req, res, next) {
res.render('about', {page:'About Us', menuId:'about'});
});
module.exports = router; // export variables
// header.js
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>XSS</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
<div class="navbar navbar-default navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">XSS-Cross-Site-Scripting</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li>About</li>
<li>Log in</li>
</ul>
</div>
</div>
<div class="container">
//footer.js
</div>
</body>
</html>
// index.js
<%- include ("_header.ejs"); %>
<h1 style="text-align: center;">Welcome to Cross-Site-Scripting</h1>
<div style="margin: auto; width: 50%; padding: 80px; border: 3px solid blue;">
<form id="contact-form" action="/send" method="POST">
<div style="text-align: center;" class="input-group">
<input type="text" class="form-control" name="userInput" placeholder="Enter something..." aria-label="Recipient's username" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-outline-secondary" id="searchBTN" type="submit"><i class="fas fa-cart-plus mr-2"></i>Send</button>
</div>
</div>
</form>
<h1 style="text-align: center;"><%= userInput %></h1>
</div>
<%- include ("_footer.ejs"); %>
So, you are sending data to the server so you need to have a POST HTTP request.
app.post('/add', (req, res) => {
let inputText = [];
inputText.push(req.body.userInput)
res.render('index', {
inputText,
});
});
Now to get the value from the user input you need to write the below code in your index.ejs file
<% if (locals.inputText){ %>
<% inputText.forEach(function (text) { %>
<h5><%= text %></h5>
<% }) %>
<% } %>

adding css to express project and ejs

im building a project in node/express/ejs and struggling to link the css to the ejs files and getting the css to show up in the browser. Ive created a public folder with a css folder inside that and the the main.css file inside. I've gone through tutorials to check how to do it but just not seeing how to fix this and get the cssto show up. Many thanks to anyone who can help :)
this is my app.js file with the app.use
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const passport = require('passport');
const flash = require('connect-flash');
const session = require('express-session');
const path = require('path');
const app = express();
// Passport Config
require('./config/passport')(passport);
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true ,useUnifiedTopology: true}
)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use('/css', express.static(__dirname + 'public/css'))
// Express body parser
app.use(express.urlencoded({ extended: true }));
// Express session
app.use(
session({
secret: 'secret',
resave: true,
saveUninitialized: true
})
);
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global variables
app.use(function(req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// Routes
app.use('/', require('./routes/index.js'));
app.use('/users', require('./routes/users.js'));
app.use(express.static(__dirname + '/public/styles/main.css'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
this is the ejs file
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<script src="https://kit.fontawesome.com/4ab1675432.js" crossorigin="anonymous"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TBANK</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<header>
<div class="logo">
<h1 class="logo-text"><span>T</span>BANK</h1>
</div>
<ul class="nav">
<li>Savings</li>
<li>Borrowing</li>
<li>Features</li>
<li>Sign Up</li>
</ul>
</header>
<div class="main-body">
<div class="home-heading">
<h1 class="home-header">Bank with the future</h1>
</div>
<!--<div class="container"><%- body %></div>-->
<div class="footer-container">
<footer class="footer_area">
<div class="row">
<div class="column">
<span>T</span>BANK
</div>
<div class="column">
<ul class="list-style-company">
<li>About us</li>
<li>Careers</li>
<li>Press</li>
<li>FAQS</li>
<li>Terms & Conditions</li>
</ul>
</div>
<div class="column">
<ul class="list-style-company">
<li>Community</li>
<li>Transparency</li>
<li>How money works</li>
<li>How we protect you</li>
<li>Business Accounts</li>
</ul>
</div>
<div class="column">
<div class="f_social_icon">
</div>
</div>
</div>
</div>
</footer>
</body>
</html>
The first step is to verify that your CSS is being served on the url you expect.
Go to your browser and check that your css is being served properly on url http://localhost:8080/css/main.css
If it is then this means you have a bad path to the css in your HTML. If its not being served properly then its either not configured properly or its at a different url.
My suspicion is that your url css/main.css(which is a url relative to the current page url) should be /css/main.css instead(which is relative to the root of your application).

Angular runs the controller multiple times

I am currently developing a chat web app. This should be realized as a single page app. For this I use Angular Router. I use socket-io to send the messages from the client to the server. Navigating between the routes actually works quite well.
In the route home.html, there is an input element for entering the message. After clicking the button, it will be added as an <li> element in the <ul> list and displayed. When starting the app, I can write messages normally. But if I navigate from the home route to another route and then go back to home and enter the message, it will be sent twice. The next time you navigate back and forth then three times, and so on. As if the controller is running several times.
I cannot find a solution to this problem on the internet. But that has to go anyway.
P.S: I have only included a script file in index.html, because I use gulp to put all the js files together in one file.
Here is the code.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<base href="/">
<title>FB4 Messenger</title>
<meta name="viewport" content="width=device-width, user-scalable=xo, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body ng-app="chatApp">
<div class="loader">
<div class="loader-text">Laden...</div>
<div class="progress">
<div class="progress-bar progress-bar-danger progress-bar-striped active" role="progressbar" style="width: 100%"></div>
</div>
<!--progress-->
</div>
<!--loader-->
<header>
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data- toggle="collapse" data-target="#collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<section class="layout">
<div class="branding">
<a href="/">
<img src="images/header/app_fh_logo.png" alt="App logo">
</a>
</div>
<!--branding-->
</section>
<!--layout-->
</div>
<!--navbar-header-->
</div>
<div class="collapse navbar-collapse" id="collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active">
<a href="/">
<span class="glyphicon glyphicon-home"></span>
Startseite
</a>
</li>
<li>
<a href="/profile">
<span class="glyphicon glyphicon-user"></span>
Konto
</a>
</li>
<li>
<a href="/about">
<span class="glyphicon glyphicon-info-sign"></span>
Über
</a>
</li>
</ul>
</div>
<!-- navbar collapse -->
</nav>
</header>
<!--header-->
<!-- ANGULAR DYNAMIC CONTENT -->
<div ng-view></div>
<script src="js/script.js"></script>
</body>
</html>
home.html
<div class="container">
<ul id="messages"></ul>
<div>
<input id="m" ng-model="message" autocomplete="off" />
<button id="send" ng-click="send()">Send</button>
</div>
</div>
about.html
<div class="container">
<div class="card">
<img class="card-img-top" src="../images/header/app_fh_logo.png" alt="Card image cap">
<div class="card-body">
<h3 class="card-title">FB4 Messenger</h3>
<p class="card-text">Version: 0.0.1 </br> Ⓒ </p>
Startseite
</div>
</div>
</div>
app.js
let $ = jQuery = require("jquery");
require("./bootstrap.min");
require("angular");
require("angular-route");
angular.module("chatApp", ["ngRoute", "appRoutes", "MainCtrl", "ProfileCtrl", "AboutCtrl"]);
$(function() {
$(".loader").fadeOut(1000);
});
appRoutes.js
angular.module("appRoutes", []).config(["$routeProvider", "$locationProvider",
function($routeProvider, $locationProvider) {
$routeProvider
.when("/", {
templateUrl: "views/home.html",
controller: "MainController"
})
.when("/profile", {
templateUrl: "views/profile.html",
//controller: "ProfileController"
})
.when("/about", {
templateUrl: "views/about.html",
//controller: "AboutController"
});
$locationProvider.html5Mode(true);
}
]);
mainCtrl.js (here the message is sent to the server)
angular.module("MainCtrl", []).controller("MainController", ["$scope",
function ($scope) {
let io = require("socket.io-client");
let socket = io.connect();
$scope.send = function () {
socket.emit("message", $scope.message);
$scope.message = "";
};
$("body").keypress(function (event) {
if (event.keyCode === 13) {
$("#send").click();
}
});
socket.on("message", function (m) {
let $li = $("<li>").text(m);
$("#messages").append($li);
});
}
]);
And the Server, index.js that receives the messages
const express = require("express");
const http = require("http");
let app = express();
let server = http.createServer(app);
app.use(express.static(__dirname + "/"));
app.get("*", function (req, res){
res.sendFile(__dirname+"/index.html");
});
let io= require("socket.io")(server);
io.on("connection", function (socket) {
socket.on("message", function (m) {
io.emit("message", m);
console.log(m);
});
});
server.listen(3000, function () {
console.log("Server runing");
});
This is problem.
$("body").keypress(function (event) {
if (event.keyCode === 13) {
$("#send").click();
}
});
Everytime your controller loads this is attached to the body as a new function. So it triggers everytime the same function call.
I suggest you could use this
$("body").removeAttr("keypress");
$("body").keypress(function (event) {
if (event.keyCode === 13) {
$("#send").click();
}
});
Better yet, use ng-click/ng-keyup and provide a function in scope
// home.html
ng-keyup="$event.keyCode == 13 && vm.sendFn()"
// in controller
vm.sendFn=function(){
... code ...for ..send
}
Edited
Can you change MainController this way and try.
It probably happens because of something similar to this -
https://github.com/angular-fullstack/generator-angular-fullstack/issues/490
let io = require("socket.io-client");
let socket = io.connect();
socket.on("message", function (m) {
let $li = $("<li>").text(m);
$("#messages").append($li);
});
angular.module("MainCtrl", []).controller("MainController", ["$scope",
function ($scope) {
$scope.send = function () {
socket.emit("message", $scope.message);
$scope.message = "";
};
}
]);

not able to load static files using express

her is my app.js which is confugaration file of express.js
<
var express = require('express')
, argv = require("optimist").argv
, fs = require("fs")
, hbs = require("hbs")
, WatsonClient = require("watson-js");
var clientId = argv.key || '5b1cb9a9c097e1100eeeebaf66117265'
, clientSecret = argv.secret || '01b8417ac6872450'
, appPort = argv.port || '3000';
function cp(source, destination, callback) {
// Read a buffer from `source`
fs.readFile(source, function(err, buf) {
if (err) { return callback(err); }
// Write that buffer to the new file `destination`
fs.writeFile(destination, buf, callback);
})
}
var Watson = new WatsonClient.Watson({ client_id: clientId, client_secret: clientSecret });
var app = express();
app.configure(function() {
console.log('inside function');
// Set the location of views and type of view engine
app.set('views',__dirname + '/app/views');
console.log(__dirname + '/app/views');
app.set('view engine', 'html');
app.engine('html', require('hbs').__express);
console.log('after view');
// Set up a standard Express configuration
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({
secret: "This is an example."
}));
app.use(app.router);
console.log('before public');
// Set the location of static assets
app.use(express.static(__dirname+'/public'));
console.log(__dirname+'/public');
console.log('after public');
});
app.get('/', function(req, res) {
res.render('layout');
});
app.post('/upload', function(req, res) {
cp(req.files.upload_file.filename.path, __dirname + req.files.upload_file.filename.name, function() {
res.send({ saved: 'saved' });
});
});
app.post('/speechToText', function(req, res) {
// Traditionally, you would store this access token somewhere safe like a database. For the purposes of this example, we're going to generate a new one on the first request and store it in the session so we don't have to deal with a database or tracking expiry and refreshing access tokens.
if(!req.session.accessToken) {
// !AT&T API: Get Access Token
Watson.getAccessToken(function(err, accessToken) {
if(err) {
// Handle an error getting an access token
res.send(err);
return;
} else {
req.session.accessToken = accessToken;
token.
Watson.speechToText(__dirname + '/public/audio/audio.wav', req.session.accessToken, function(err, reply) {
if(err) {
res.send(err);
return;
}
res.send(reply);
return;
});
}
});
} else {
Watson.speechToText(__dirname + '/public/audio/audio.wav', req.session.accessToken, function(err, reply) {
if(err) {
res.send(err);
return;
}
return;
});
}
});
app.listen(appPort);
console.log('AT&T Speech API Basic Walkthrough App started on Port ' + appPort + '.');
// !USAGE: node app.js --key= --secret= --port=
// !SETUP: Dependencies
/*
* Express: Minimal web application framework
* FS: Node.js File System module
* Optimist: Lightweight option parsing
* HBS: Express View Engine wrapper for Handlebars
* Watson.js: Simple API Wrapper for the AT&T Speech API
*/
and my layout.html is
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>AT&T Speech API Example: Basic Walkthrough</title>
<meta name="description" content="Application for the AT&T Speech API Deep Dive Presentation at DevLab 2012">
<meta name="author" content="Michael Owens">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="public/styles/bootstrap.css">
<link rel="stylesheet" href="public/styles/example-basic.css">
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js'></script>
</head>
<body>
<a onclick="Recorder.playBack('audio');" href="javascript:void(0);" title="Play">
Play
</a>
<div class="container">
<div class="row">
<div class="span12">
</div>
</div>
<div class="row">
<div class="span4">
<h2 id="progress-title">Progress (Step <span id="progress-step">1</span> of 5)</h2>
<div id="progress-indicator" class="progress progress-striped">
<div class="bar" style="width: 20%;"></div>
</div>
<ol class="progress-list">
<li id="progress-01" class="active">Access User's Microphone</li>
<li id="progress-02">Record Audio from Mic</li>
<li id="progress-03">Save Audio to File</li>
<li id="progress-04">POST File to AT&T Speech API</li>
<li id="progress-05">Receive Results from AT&T Speech API</li>
</ol>
<div>
<i class="icon-refresh"></i> Start Over
</div>
</div>
<div class="span8">
<h2>Current Status</h2>
<div id="status-mic" class="alert alert-info">
Audio Status: <strong>waiting</strong>
</div>
<div id="status-upload" class="alert alert-info">
File Status: <strong>waiting</strong>
</div>
<div id="control_panel">
<div class="btn-group">
<button id="button-connect" class="btn btn-large btn-success"><i class="icon-off icon-white"></i> <span class="action">Connect</span></button>
<button id="button-recorder" class="btn btn-large" disabled="disabled"><i class="icon-music"></i> <span class="action">Record</span></button>
<span id="button-save" class="btn">
<button disabled="disabled" class="btn btn-large"><i class="icon-download-alt"></i> <span class="action">Save</span></button>
<span id="save_button"><span id="flashcontent"></span></span>
</span>
<button id="button-transcribe" class="btn btn-large" disabled="disabled"><i class="icon-share-alt"></i> <span class="action">Transcribe</span></button>
</div>
</div>
<div id="transcribe-container">
<h2>Speech API Response</h2>
<div id="transcribe-response"></div>
</div>
</div>
</div>
<form id="uploadForm" name="uploadForm" action="/upload" >
<input name="authenticity_token" value="xxxxx" type="hidden">
<input name="upload_file[parent_id]" value="1" type="hidden">
<input name="format" value="json" type="hidden">
</form>
<script type="text/javascript" src="public/scripts/swfobject.js"></script>
<script type="text/javascript" src="public/scripts/example-basic.js"></script>
</div>
</body>
</html>
When i run app.js on node in cmd, it gives me error of not able to load static files i.e js and css files but it load view part i.e layout.html
exact errors is
<
GET h://ip:3000/public/scripts/swfobject.js 404 (Not Found)
GET h://ip:3000/public/scripts/example-basic.js 404 (Not Found)
GET h://ip:3000/public/styles/bootstrap.css 404 (Not Found)
GET h://ip:3000/public/styles/example-basic.css 404 (Not Found)
>
ip -localhost
h -https
my foldr structute is
example(parent folder)
subfolders
app/views/layout.html(code is given above)
public/scripts/js files
public/styles/css files
app.js(code is given above)
all the above subfolder(app,public,app.js) at the same level
so please suggest me some thing
It should work if you remove the 'public' from your URLs, like:
<link rel="stylesheet" href="/styles/bootstrap.css">
<link rel="stylesheet" href="/styles/example-basic.css">
You setup the static directory to be /public so its going to look in there for static resources. You did that here:
app.use(express.static(__dirname+'/public'));
When you add public to those URLs, it will be looking in /public for a folder called public, which it won't find. It will however find a folder called styles.

Categories

Resources