Why doesn't this "res.redirect()" redirect? - html

I'm trying to redirect using nodejs and expressjs, but when I click on button nothing happens only url changes.
I'm using a form and within it has a button, this form has an action to "/failure"
const express = require("express")
const bodyparser = require("body-parser")
const request = require("request")
const app = express()
app.use(express.static("public"))
app.use(bodyparser.urlencoded({
extended: true
}))
app.get("/", function (req, res) {
res.sendFile(__dirname + "/signup.html")
})
app.post("/failure", function(req, res){
res.redirect("/")
})
app.listen(3000, function () {
console.log("Server is running on port 3000")
})
<!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>Failure</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-4">Uh oh!</h1>
<p class="lead">There was a problem signip you up Please try again or contact the developer!.</p>
<form action="/failure" method="POST">
<button class="btn btn-lg btn-warning" type="submit" name="button">Try again</button>
</form>
</div>
</div>
</body>
</html>

Have you tried
res.redirect(307, '/test');
});
This will preserve the send method, for more info you can check http://www.alanflavell.org.uk/www/post-redirect.html

This behavior is correct. You are posting to the '/failure' route and within the handler of that route, it is redirecting to get '/' route handler which will return signup.html - which was your starting point.
You are posting to this:
app.post("/failure", function(req, res){
res.redirect("/") // this is redirecting your route handler '/' which serves 'signup.html
})

Related

Including ejs partial with listner button not working; how to fix static?

I am trying to include a partial on the page with my backend coming later. I want to use an event listener button. It dosent work. I am using express.ejs and node.js with vanilla js.
I am using this for my vanilla js
const button = document.getElementById('button')
button.addEventListener('click',()=>{
const hi = document.createElement(`<%-require('../views/partials/hi.ejs')%>`)
document.appendChild(hi)
})
this for my 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>hi</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<button id="button">Im a button</button>
<script src="main.js" type="module"></script>
</body>
</html>
and this for my node
const express = require('express')
const app = express()
app.set('view engine','ejs')
app.use(express.static('public'))
app.get('/',(req,res)=>{
res.render('layout')
})
app.listen(5000,()=>{
console.log('server listening')
})
I get this error when i try to use the partial with the button
main.js:4 Uncaught DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('<%-require('../views/partials/hi.ejs')%>') is not a valid name.
at HTMLButtonElement.<anonymous> (http://localhost:5000/main.js:4:25)
this comes from client side....why and how to fix?

how to retrieve nodejs scraped data and display in html

I am trying to scrape a website for some content using NodeJs, it all works good but then the scraped text is desplayed in the console only however, i want to pass my scraped data to my html page (index.html), but didn't know how to do that.
here is my nodejs file (scrape.js)
const request = require('request');
const cheerio = require('cheerio');
request('https://store.steampowered.com/search/?filter=weeklongdeals', (error, response, html) =>{
if(!error && response.statusCode == 200){
const $ = cheerio.load(html);
$('.title').each((i,ele) => {
const title = $(ele).text();
console.log(title);
});
}
})
and here is my html file where the data should displayed in(index.html)
<!DOCTYPE html>
<html>
<title>Real Time Data</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="bgimg w3-display-container w3-animate-opacity w3-text-white">
<div class="w3-display-topleft w3-padding-large w3-xlarge">
Real Time Data
</div>
<div class="w3-display-middle">
<h1 class="w3-jumbo w3-animate-top">Real Time Data</h1>
<center>
<div id="getDDta">
<table>
<tr>
<th>Title</th>
</tr>
<tr>
<td>Data...</td>
</tr>
</table>
</div>
</center>
</div>
<div class="w3-display-bottomleft w3-padding-large">
Powered by
Real Time Data</a>
</div>
</div>
</body>
</html>
my request is very simple, i want to display the scraped data in nodejs (scrape.js) in (index.html)
You should be able to use EJS (or perhaps any other templating engine) for this purpose.
We download the titles to an array, then render using ejs.render.
Make sure you install ejs using
npm install ejs
In your project you'll need to create the following structure:
/index.js
/views/index.ejs
index.js
const request = require('request');
const cheerio = require('cheerio');
const express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
request('https://store.steampowered.com/search/?filter=weeklongdeals', (error, response, html) => {
if(!error && response.statusCode == 200) {
const $ = cheerio.load(html);
let titles = [];
$('.title').each((i,ele) => {
const title = $(ele).text();
console.log(title);
titles.push(title);
});
res.render('index', { titles });
}
})
});
app.listen(8080);
console.log('Express listening on port 8080');
index.ejs
<!DOCTYPE html>
<html>
<title>Real Time Data</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<body style="padding: 2em">
<table class="table table-striped table-bordered">
<tr>
<th>Title</th>
</tr>
<% for (let title of titles) { %>
<tr>
<td><%= title %></td>
</tr>
<% } %>
</table>
</body>
</html>
Then navigate to localhost:8080/ to see your rendered page.
I've created an online example here
What #Terry said, but use get and map rather than pushing elements in an each loop:
let titles = $('.title').get().map(e => $(e).text())

res.sendFile not rendering html

I am trying to render HTML with res.sendFile using absolute path but it is sending encoded HTML in a pre tag so the response shows HTML unrendered in a pre tag.
Here is my express code
app.get('/', (req,res) =>{
res.sendFile(__dirname+'/a.html');
});
and here 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">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>I am Html</h1>
</body>
</html>
and here is the result when I navigate to localhost:8800/
<!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>Document</title>
</head>
<body>
<h1>I am Html</h1>
</body>
</html>
It prints the html as it is without rendering it.
You need to use res.render() to actually render the html.
I can't post a comment because I don't have enough reputation, but what I was going to say is that I ran your code on my system (OSX Mojave 10.14.6, Node v12.13.0, latest versions of Firefox and Chrome) with some additions to make it work (posted below), and didn't run into your problem. Perhaps you have some other code or middleware that you haven't posted. Also, you are correct that res.render is for templates.
const express = require('express');
const app = express();
const port = 3000;
const path = require('path');
app.get('/', (req, res) => {
res.sendFile(__dirname + '/a.html');
// better to use the path API, but both work
// res.sendFile(path.join(__dirname, 'a.html'));
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
The HTML is the same. Folder structure is:
.
├── app.js
├── a.html
Could you post more details?

How ejs template is loaded on browser? How frontend interact with backend?

Working on frontend and backend using NodeJs for server side and ejs template for frontend. Came across a feature while using ejs scriplets to display data send from server while loading page.
Used <%console.log()%> over ejs, thought this log will be seen on inspect element logs, however got message over server terminal. How did this information is send over to server without any form submit or API call?
Server app.js:
/*jshint multistr: true, node: true, esversion: 6, undef: true, unused: true, varstmt: true*/
"use strict";
// NPM Modules
const express = require('express'),
path = require('path');
const app = express();
// Setup views directory, file type and public filder.
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.render('index', {message:'Welcome'});
});
const port = process.env.PORT || 3000;
console.log('server listening at http://127.0.0.1 over port: ', port);
app.listen(port);
EJS template index.ejs:
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<!-- All these CSS files are in plublic directory, as we had made all the content of public directory available for anyone from app.js -->
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="/css/app.css" />
<link rel="shortcut icon" href="logo.jpg" />
<title>Sign-Up/Login Form</title>
</head>
<body>
<%console.log(message)%>
<%=message%>
<%console.log("anything")%>
</body>
</html>
How can all the <%console.log()%> are send over server terminal and <%=message%> is displayed over browser. Even <%console.log("anything")%> is displayed over server terminal even though this has nothing to do with server. How ejs scriplets communicate with server and not browser?
Had anyone else tried this before or observed it.
Your question is about how ejs templates work. This is an answer for that question. I think you might also have something wonky going on with your express setup causing you problems.
EJS is a server-side rendering system. It's job is done before the html is sent to the client, so it has nothing to do with the browser.
The scriptlets inside <% %> run on the server to insert content into the template before sending to the client.
If you want to print something out on the browser console, don't put it in a scriptlet, just put it into a <script> tag, like this:
<script>
console.log("foo");
</script>
If you want the browser console to print something generated by the server, you could use ejs to put the value of message into what it generates:
<script>
console.log("<%=message%>");
</script>
The server will put the value of message into a console.log() statement that gets delivered to the browser.
This example prints "Wellcomes" to the browser console:
server:
const bodyParser = require('body-parser'),
express = require('express'),
path = require('path');
const app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.render('index', { message: 'Wellcomes' });
});
const port = process.env.PORT || 3000;
const listener = app.listen(port, function() {
console.log('platform listening on', listener.address().port);
});
index.ejs:
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Sign-Up/Login Form</title>
</head>
<body>
<script>
console.log("<%=message %>");
</script>
</body>
</html>
If you show page source in your browser, you should see:
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Sign-Up/Login Form</title>
</head>
<body>
<script>
console.log("Wellcomes");
</script>
</body>
</html>

How to keep master page on page reload in HTML using AngularJS

In my application i have declared ng-app in Master.html and added all script, stylesheet references in it
this is my master page
<html ng-app="mainApp">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>AdminLTE 2 | Dashboard</title>
<script src="../Angular/angular.min.js"></script>
<script src="../Angular/angular-route.js"></script>
<script src="../Scripts/AngularServices/App.js"></script>
</head>
<body class="hold-transition skin-blue sidebar-mini">
<li><i class="fa fa-circle-o"></i>Group</li>
<li><i class="fa fa-circle-o"></i>Member</li>
<section class="content">
<div ng-view></div>
</section>
</body>
</html>
App.js
var mainApp = angular.module("mainApp", ['ngRoute'])
mainApp.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/main/Group', { templateUrl: '/Portal/Group.html', controller: 'GroupController' }),
$routeProvider.when('/main/Member', { templateUrl: '/Portal/Member.html', controller: 'MemberController' });
$locationProvider.html5Mode(true);
});
// group
mainApp.controller('GroupController', function ($scope, $http) {
$http.get('/api/APIGroup/GetGroupDetails').then(function (result) {
$scope.group = result.data;
});
});
Group.html
<div ng-controller="GroupController">
<div class="row">
<h1>Welcome to group</h1>
my content here
</div>
</div>
when i execute master page and if click group link group.html form opening inside master page my url like this
http://localhost:50810/main/chitGroup
but if reload page here am getting error as
Server Error in '/' Application.
The resource cannot be found.
Master page not applying to how to fix this
In your angular.app you have ngRoute to handle your states for create Single Page Application.
ngRoute need to pass the state names correctly as ng-href="#!/main/Group", that because when you use ngRoute the url changed automaticly to http://localhost:50810/#!/
Server Error in '/' Application.
The resource cannot be found.
This error because you redirect to http://localhost:50810 to find /main/Group which not exist.