I'm working on a website using Node.js with Express and EJS as the templating engine, and I'm having trouble getting data from the form on the site. Here is my code:
app.js
//app.js
'use strict';
var debug = require('debug');
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var app = express();
const { getSearchPage, search } = require('./routes/search');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function () {
debug('Express server listening on port ' + server.address().port);
});
app.get('/search', getSearchPage);
app.post('/search', search);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
search.js
//search.js (in routes folder)
module.exports = {
getSearchPage: (req, res) => {
res.render('search.ejs');
},
search: (req, res) => {
var artist = req.body.searchArtist;
var song = req.body.searchSong;
var genre = req.body.searchGenre;
var decade = req.body.searchDecade;
console.log("The variables from the page: ", req.body, artist, song, genre, decade); //logs "{} undefined undefined undefined undefined"
if (song) {
//query the database and return some results
}
res.render('search.ejs', { outputArray: outputArray });
}
}
search.ejs
<!DOCTYPE html>
<html lang="en" and dir="Itr">
<head>
<meta charset="utf-8">
<title>Home</title>
<!--link rel="stylesheet" href="css/search.css"-->
<script src="https://kit.fontawesome.com/9b28d88510.js" crossorigin="anonymous"></script>
</head>
<body>
<form method="post" enctype="multipart/form-data">
<div class="search-box">
<input class="search-txt" type="text" name="searchSong" placeholder="Type to search">
<a class="search-btn" href="#">
<i class="fas fa-search"></i>
</a>
</div>
<div class="search-box2">
<input class="search-txt2" type="text" name="searchArtist" placeholder="Type to search">
<a class="search-btn2" href="#">
<i class="fas fa-search"></i>
</a>
</div>
<div class="search-box3">
<input class="search-txt3" type="text" name="searchGenre" placeholder="Type to search">
<a class="search-btn3" href="#">
<i class="fas fa-search"></i>
</a>
</div>
<div class="search-box4">
<input class="search-txt4" type="text" name="searchDecade" placeholder="Type to search">
<a class="search-btn4" href="#">
<i class="fas fa-search"></i>
</a>
</div>
<button type="submit">Search!</button>
</form>
<% if(typeof outputArray != 'undefined'){%>
<ul>
<% outputArray.forEach(function(song) { %>
<li><%= song %></li>
<% }); %>
<% } %>
</ul>
</body>
</html>
I've tried setting urlencoded({extended: }) to true and to false, I've tried changing the form type to application/x-www-form-urlencoded, I've tried changing the post to a get, I've made sure I have body-parser installed, I've tried putting the routes before the server declaration. I've read through most of the pages here on the same issue, but none of those fixes have worked for me. Even more confusingly, I'm following almost exactly with this tutorial, and I don't think I've missed anything that they did. This is my first time ever using Node.js/Express.js/EJS, but I've read through countless forum posts on this exact topic and I still can't figure out where it's going wrong.
You have body parsers capable of handling requests formatted as JSON or URL Encoded data.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
… but your form isn't using either of those:
<form method="post" enctype="multipart/form-data">
You don't have any file inputs, so there is no reason to use multipart/form-data (which is more bandwidth intensive that the default URL encoded data).
Remove the enctype attribute.
If you wanted to support file inputs then you would need to support multipart/form-data.
One way to do that is to use the express-fileupload module, which the tutorial you linked to recommends but you didn't use.
Related
I am currently learning express.js and building a dynamic website with firebase. The website is really simple, it takes two numbers from user input and sends back the sum. I have one test.html in the public folder, which contains the html form, inputs, and submit button. In index.js in the functions folder I specified the app.post method, and in firebase.json in my project folder the rewrite properties is the same as the tutorial from firebase: Use a web framework.
/public/test.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Calculator</h1>
<form action="/test" method="post">
<input type="text" name="num1" placeholder="Enter your first number">
<input type="text" name="num2" placeholder="Enter your second number">
<button type="submit" name="submit">Submit</button>
</form>
</body>
</html>
/functions/index.js:
const functions = require("firebase-functions");
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/test", (req, res) => {
res.send("The answer is " + (Number(req.body.num1) + Number(req.body.num2)));
});
exports.app = functions.https.onRequest(app);
/firebase.json:
{
"hosting": {
"public": "public",
......
"rewrites": [ {
"source": "**",
"function": "app"
} ]
}
......
}
When I open the page, the form, boxes, and submit button appear just as specified in the test.html file. I expect that when I enter two numbers in the input boxes the website would return their sum, as specified in index.js. However, when I click the submit button, nothing happens.
app.get('/all-datas', (req, res) => {
data.find({}, function (err, names) {
res.render('EJS.ejs', {
nameList: Uname
})
})
})
I want this code to be used in my javaScript but when http://localhost:5000/all-datas is accessed this the page does not render and keeps loading and loading
or just tell me the any other way
I have installed all required modules
tried changing the port
done lots and lots changes still i cant help
I also had the same problem. The cause of the problem in my case was that I was not redirecting when handling post request.
app.js
const express=require("express")
const bodyparser=require("body-parser")
const path=require("path")
const app=express()
app.set("view engine", "ejs")
app.set("views", path.join(__dirname, "views"))
app.use(bodyparser.urlencoded({extended:true}))
const list=[]
app.get("/", (req, res)=>{
const day=new Date()
const options={
weekday:"long",
day:"numeric",
month:"long"
}
const today=day.toLocaleDateString("en-US", options)
res.render("list.ejs", {day:today, list:list})
})
app.post("/", (req, res)=>{
const task=req.body.newItem
list.push(task)
res.redirect("/")
})
app.listen(3000)
list.ejs
<!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>
<h1><%=day%></h1>
<h2>To Do List</h2>
<ul style="list-style-type: none; margin:0; padding: 0;">
<%for(let i=0; i<list.length; i++){%>
<li><%=list[i]%></li>
<%}%>
</ul>
<form action="/" method="post">
<input type="text" name="newItem">
<input type="submit" value="Add">
</form>
</body>
</html>
First of all, you don't need to specify the extension on '.ejs' on render. you are also not using the 'names" parameter inside the callback function. if you want to take 'Uname' from 'names'( Output docs of the query ), you can pass the whole array to ejs and take "uname" from there by using a loop (ex: forEach Loop).
To render all usernames form the Namelist
app.get('/all-datas', (req, res) => {
data.find({}, function (err, names) {
res.render('EJS', {
nameList: names
})
})
})
on Ejs :
<% nameList.ForEach((item)=>{ %>
<p> username: <%= item.Uname %> </p>
<% }) %>
If This doesn't work, Make sure you have written the loop on the Ejs file correctly.
campground data i m working on this web app from a course where i m using mongodb ,the database is created (named as "campit") and collection is named as campground(but mongo has named it campgrounds as usual) .the collection consist of name and image. a route (namely "/create") is not working,
by going to url "localhost:3000/create.ejs" its showing Cannot GET /index.ejs
here is my code,this is app.js file
var express=require("express");
var app=express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/campit");
var campgroundSchema=new mongoose.Schema({
name:String,
image:String
});
app.get("/create",function(req,res){
campground.find({},function(err,campground){
if(err){
console.log(err)
}
else{
console.log("successfully shown");
res.render("index.ejs",{campgrounds:campground})
}
});
app.listen("3000",function(){
console.log("listening from server 3000");
});
this is index.ejs file,which is supposed to show
<div class="container">
<div class="row no-gutters">
<% campgrounds.forEach(function(camp){ %>
<div class="col col-lg-4 img-thumbnail">
<img class="but" height="75%" width="100%" src="<%=camp.image%>" alt="image">
<div class="text-center">
<h6><%= camp.name %> </h6>
<button class="btn btn-outline-info " type="button" name="more info"> more info</button>
</div>
</div>
<% }); %>
</div>
</div>
EDIT
when i m going to /create route it shows that campgrounds.forEach is not a function error......whole code is same, something is wrong with rendering variable..... and i m sure that campgrounds contain data.
EDIT CLOSE
any kind of help will be highly appriciated.
thank you.....
You are hitting wrong url. As you can see in you code.
app.get("/create", function(req,res){
campground.find({},function(err,campground){
if(err){
console.log(err)
}
else{
console.log("successfully shown");
res.render("index.ejs",{campgrounds:campground})
}
}
});
Route you should be using is /create and not /create.ejs. index.ejs is the template rendered when you visit /create route
Use this url localhost:3000/create instead of localhost:3000/create.ejs :)
In your Javascript file, you wrote app.get('/create'). create.ejs its just the name of your template. The path of your route and the name of your template doesn't need to be the same.
Try using:
var router = express.Router();
router.route('/create')
.get(function(req,res){
campground.find({},function(err,campground){
if(err){
console.log(err)
}
else{
console.log("successfully shown");
res.render("index.ejs",{campgrounds:campground})
}
});
app.use('', router);
You forget to set view engine, use code below after app.use(bodyParser.urlencoded({extended:true}));
USE IT
app.set("view engine", "ejs");
I use angularJS+passport to perform user authentication and hence, i set up these below.
HTML:
<div ng-controller="logincontroller">
<form>
Email:<input type="text" ng-model="user.email"/>
Password:<input type="password" ng-model="user.password"/>
<div ng-click=loginUser()>Submit</div>
</form>
</div>
In client side javascript:
app.controller('logincontroller',function($scope,$http){
$scope.loginUser=function(){
$http.post('/loginUser',JSON.stringify($scope.user));
}
})
ON app.js
var bodyParser = require('body-parser');
var cookieParser=require('cookie-parser');
var passport=require('passport');
var LocalStrategy=require('passport-local').Strategy();
var session=require('express-session');
app.use(express.session({secret:"flibbertygibbit"}));
app.use(cookieParser());
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.json());
passport.use(new LocalStrategy(
{usernameField: 'user.email',
passwordField: 'user.password',
passReqToCallback: true
},
function(username,password,done){
console.log("am here"+username+" "+password);
}
))
app.post('/loginUser',passport.authenticate('local'));
The problem i face is the Local strategy isnot being called at all and all I get Typerror: Local strategy requires a verify callback. I ain't sure where i went wrong, being novice at it. Please help.
The error you're getting is caused by this:
var LocalStrategy=require('passport-local').Strategy();
^^
You're calling the Strategy class without any arguments, so this results in the error. You want to store a reference to the class itself, like this:
var LocalStrategy=require('passport-local').Strategy;
Also, because you're setting passReqToCallback : true, the verification callback will take four arguments, not three. It should look like this:
function(req, username, password, done) { ... }
Objective: I'm new to Node.js and Express.js framework. Currently I'm writing a small app using IONIC framework where I trying to pass user basic details like FirstName, LastName to node.js server as a matter of first step. Then once I read the data I'm planning to save the data in the database.
Issue: Currently when I pass the details (in this case just FirstName for testing purpose) through POST request from my app to the node js server and when i try to access the FirstName using req.body.FirstName, the server returns "undefined".However when I use console.log(req.body) it returns the value for eg., { '{"FirstName":"test"}': '' }.
I'm not sure where did I miss. I suppose I referred a lot of links thru Google, nothing seems to be working out. It might be a simple thing, but it is bothering me lot and I'm wasting time to find the solution.
Configuration:
Express.js - 4.13.3
I've tried different combination based on the related links for this issue. Nothing seems to be working. Any guidance or advise will be really helpful as I got struck in this.
serverapp.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,POST');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.post('/', function(req, res) {
console.log("Hi from server", req.body);
console.log("Hi this is key value", req.body.FirstName); // this throws error as undefined
});
var server = app.listen(8100, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
Code snippet from Controllers.js - Post request is sent via this.
var url = 'http://localhost:8100'
var request = $http.post(url,
{'FirstName': $scope.Model.FName}, {headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}});
Rego.html file
<form name="tab-Registration.form">
<div class="list" align="left">
<label class="all_page_bgColor" align="left">
<input type="text" name="FName" placeholder="First Name" ng-model="Model.FName" class="all_page_bgColor" align="left">
</label>
<label class="all_page_bgColor" align="left">
<input type="text" name="LName" placeholder="Last Name" ng-model="Model.LName" class="all_page_bgColor" align="left">
</label>
<label class="all_page_bgColor" align="left"> <!-- class="item item-input" -->
<input type="text" name="Email" placeholder="Email" ng-model="Model.Email" class="all_page_bgColor" align="left">
</label>
<label class="all_page_bgColor" align="left">
<input type="text" name="PhoneNo" placeholder="Phone" ng-model="Model.PhoneNo" class="all_page_bgColor" align="left">
</label>
</div>
<div align = "center">
<button class="button button-assertive" ng-click="submit()">Submit</button>
</div>
</form>
This object { '{"FirstName":"test"}': '' } has only one key which is {"FirstName":"test"} and the value is empty string. Actually the whole object is the key of first value.
Object must be like this: {"FirstName":"test"}
But i don't know how things end up like this. You have FName in your form but you get this, and I don't know what this IONIC framework is and how it works. I think it's better to start with experimenting with express.js then switch to higher level frameworks.
I've resolved this. The solution is to use transformRequest while sending the request to the server for URL encoded data, coz the request send to server by default sends Json object. And when you want to over-ride that, you have to use transformRequest
$http({
method: 'POST',
url: url,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {
FirstName: $scope.Model.FName}