I am building a simple web application with HTML, CSS and postgreSQL.
I am building a web back end using Node.js, and trying to store app data using a SQL database. The form collects comments from user, stores in database and also displays the comments in the html. I keep getting an error in my code.
<!DOCTYPE html>
<html>
<head>
<title>Editor</title>
<link rel="stylesheet" href="stylesheets/stylesheet.css">
<link rel="shortcut icon" href="">
</head>
<body>
<div id="commentNav" contenteditable="true">
<h1>Comments</h1>
<form action="/comments" method="POST">
<input type="text" name="name" placeholder="First Name"/>
<textarea rows="4" name="comment">Describe your favorite</textarea>
<input type="submit" value="Submit"/>
</form>
<section id="suggestions">
<h2>Comment List</h2>
</section>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="javascripts/script.js"></script>
</body>
</html>
Script.js
getComments();
function getComments(){
$.get("/comments", function(data){
if(!data){
console.log("No data recieved");
}
console.log("recieved data:");
for(let i = 0; i < data.length; i++){
console.log(data[i].name);
}
showComments(data);
});
}
function showComments(comments){
let commentSection = document.getElementById("suggestions");
// for(let i = 0; i < comments.length; i ++){
for (let i in comments){
let section = document.createElement("section");
section.className += "suggestion";
let heading = document.createElement("h3");
heading.innerHTML = comments[i].name;
let comment = document.createElement("p");
comment.innerHTML = comments[i].comment;
section.appendChild(heading);
section.appendChild(comment);
commentsSection.appendChild(section);
}
}
Server.js
const express = require('express');
let pg = require('pg');
let pg = new pg.Database('db/comments.db');
const app = express();
const PORT = 8080;
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile('index.html', { root: path.join(__dirname, './files') });
});
app.listen(PORT, () => {
console.log(`Example app listening on port ${PORT}!`);
});
app.get('/comments', function(request, response){
console.log("GET request recieved at /comments");
db.all('SELECT * FROM comments', function(err, rows){
if(err){
console.log("Error: " + err);
}
else{
response.send(rows);
}
})
});
app.post('/comments', function(request, response){
console.log('POST request recieved at /comments');
});
Error:
Failed to load resource: the server responded with a status of 404 (Not Found)
Connection to database using node-postgres js module has to be done as following:
const client = new Client({
user: 'dbuser',
host: 'database.server.com',
database: 'mydb',
password: 'secretpassword',
port: 3211,
})
client.connect()
For more info see documentation
Related
I am trying to create a calculator app using express.js to get request for an html file and a post request that takes the user's input and responds with the answer. However, I want to display my answer inside a html container without the page redirecting. Is there a way to achieve this with vanilla javascript?
index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="styles.css" />
<link rel="shortcut icon" href="#" />
<title>Calculator</title>
</head>
<body>
<h1>Calculator App</h1>
<form action="/" method="post" class="ajax">
<label for="userInput">Enter Equation</label>
<input type="text" id="equation" name="equation" />
<button type="submit" id="btn_submit">Calculate</button>
</form>
<div class="container"></div>
</body>
</html>
app.js
const express = require('express');
const app = express();
port = 3000;
app.use(express.urlencoded({ extended : false }));
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile(__dirname + public);
});
app.post('/', (req, res) => {
let equation = req.body.equation;
console.log(equation);
let result = eval(equation);
res.status(200).send('Result is ' + result);
});
app.listen(port, ()=> {
console.log('Hosted on port: ' + port);
});
CalculatorApp
Evaluated Expression
You will need to write front end JavaScript code to make the ajax request instead of having the form action submit the request. The JavaScript will receive the response and can update the value on the HTML.
app.post('/', (req, res) => {
let equation = req.body.equation;
console.log(equation);
let result = eval(equation);
res.status(200).json({ value: `Result is ${result}` });
});
<script>
document.querySelector('form').addEventListener('submit',submitEquation);
function submitEquation(event){
event.preventDefault();
const input = document.querySelector('#equation');
const equation = input.value;
const clearInput = true;
if(clearInput){
input.textContent = '';
}
fetch(window.location.origin, {
method: 'post',
body: JSON.stringify({ equation })
})
.then(response => response.json())
.then(json => {
document.querySelector('.container').textContent = json.value;
})
}
</script>
I am getting an uncaught TyperError in this chat application prototype.
HTML file (also contains Vue.js script)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fireside Chat</title>
</head>
<body>
<h1>Fireside Chat</h1>
<div id="app">
<ul>
<li v-for="messageVar in messages">
{{ messageVar }}
</li>
</ul>
<form #submit.prevent="sendMessage">
<input type="text" placeHolder="Message..." v-model:value="message"/>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = null;
var app = new Vue({
el: '#app',
data: {
message: '',
messages: ''
},
methods: {
sendMessage: function () {
socket.emit('message', this.message);
this.message = '';
}
},
created: function () {
socket = io();
},
mounted: function () {
socket.on('message'), function (message) {
app.messages.push // context of callback function is different
}
}
})
</script>
</body>
</html>
Server file:
const express = require('express')
const app = express()
const http = require('http').Server(app)
const io = require('socket.io')(http)
app.use('/style', express.static(__dirname + '/style'))
app.get('/', (req, res) => res.sendFile(__dirname + '/index.html'))
io.on('connection', (socket) => {
socket.on('message', (msg) => console.log(msg)) // successful
socket.on('message', (msg) => io.emit('message', msg)) // UNSUCCESSFUL - WHY?
})
// start up http server
http.listen(3000, () => console.log('Listening on port 3000'))
I run the code in a development environment using the command
node serverFileName.js and test the application at http://localhost:3000/
In the server file code I am able to successfully log a message to the console (it shows up in the terminal window where I started the development node server), but when I try to emit the message to the client using socket.io I see this error message on the console:
Uncaught TypeError: Cannot read property 'apply' of undefined at
Socket../node_modules/component-emitter/index.js.Emitter.emit (index.js:145)
The code at the specified line in index.js is this:
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
Why is this emit function failing?
Please educate me about how am I going to connect the CSS to the server. I've followed two tutorials on youtube, one is using node.js and nodemailer. With this, I use a localhost to run my website but the CSS and js I made from the second tutorial (pop-up when button is clicked) won't work on the localhost but when I clicked the html file itself.
Is this because the tutorials are for different kinds of website? like static and dynamic?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewpoint" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="style.css" rel="stylesheet" type="text/css" />
<title>Document</title>
</head>
<body>
<h1>Welcome to my App</h1>
<form>
<div>
<label for="email">Sender's Email: </label>
<input type="email" id="email" placeholder="Your Email"> <br>
</div>
<div>
<label for="classNum">To whom: R</label>
<input type="number" id="classNum" placeholder="class#" min="1" max="31"> <br>
</div>
<div>
<label for="subject">Subject: </label>
<input type="text" id="subject" placeholder="Subject"> <br>
</div>
<div>
<label for="text">Letter: </label> <br>
<textarea name="text" id="text" cols="30" rows="10"></textarea> <br>
</div>
<input type="submit" value="Submit" class="modal-button" data-modal-target="#modal">
<div class="modal" id="modal">
<div class="modal-header">
<div class="title">Letter Sent!</div>
</div>
<div class="modal-body">
Pressing this button will refresh the page.
<div><button data-close-button class="refresh-button">Send another letter</button></div>
</div>
</div>
<div id="overlay"></div>
</form>
<script src="script.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$('form').on('submit', (e) => {
e.preventDefault();
const email = $('#email').val().trim();
const subject = $('#subject').val().trim();
const text = $('#text').val().trim();
const classNum = $('#classNum').val().trim();
const data = {
email,
subject,
text,
classNum
};
$.post('/email', data, function(){
console.log('Server received our data')
});
});;
</script>
</body>
</html>
This is the server.js
const express = require('express');
const sendMail = require('./mail')
const log = console.log;
const app = express();
const path = require('path');
const PORT = 8080;
app.use(express.urlencoded({
extended: false
}));
app.use(express.json());
app.post('/email', (req, res) => {
const { subject, email, text, classNum} = req.body;
console.log('Data: ', req.body);
sendMail(email, subject, text, classNum, function(err, data){
if (err){
res.status(500).json({ message: 'Internal Error'});
}
else{
res.json({ message: 'Email sent!' });
}
});
// res.json({ message: 'Message received!' })
});
app.get('/', (req, res) =>{
res.sendFile(path.join(__dirname, 'views', 'index.html'));
});
app.listen(PORT, () => log('Server is starting on PORT: ', 8080));
And this one is for the pop-up, script.js
const openModalButtons = document.querySelectorAll('[data-modal-target]');
const closeModalButtons = document.querySelectorAll('[data-close-button]');
const overlay = document.getElementById('overlay');
var path = require('path') //from stackoverflow
app.use(express.static(path.join(__dirname, 'public')));
openModalButtons.forEach(button => {
button.addEventListener('click', () => {
const modal = document.querySelector(button.dataset.modalTarget)
openModal(modal)
})
})
closeModalButtons.forEach(button => {
button.addEventListener('click', () => {
const modal = button.closest('.modal')
closeModal(modal)
})
})
function openModal(modal) {
if (modal == null) return
modal.classList.add('active')
overlay.classList.add('active')
}
function closeModal(modal) {
if (modal == null) return
window.open("https://www.w3schools.com");
}
Please tell me if I need to include the CSS and the mail.js .
If you want to allow users or browsers to get files from your server, you need to add them to your server-side code. For example, you've added a stylesheet reference to your index.html, so the browser will try to get that file (/style.css) from the server. You haven't put any reference to this on the server side, so the server will respond with 404 Not Found or another error.
In order to make the server respond to a request for "/style.css", you need to add the following to your server-side index.js:
app.get("/style.css" /*name of file in index.html*/, (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'style.css')); //CHANGE THIS TO THE NAME OF THE FILE ON THE SERVER
});
The same needs to happen for your browser script, script.js:
app.get("/script.js" /*name of file in index.html*/, (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'script.js'));
});
app.get tells express to respond to a GET request to the first parameter: in the example, that's "/style.css". If you wanted to respond to a GET request to "/foobar", then you would write app.get("/foobar", (req, res) => {/*SOME CODE HERE*/}); . The reason why it wasn't working was becuase when the browser tried to find style.css and script.js, the server didn't know what to do because you hadn't included app.get for those files, and therefore responded with an error.
This might be confusing due to the architecture of how this works. Look at this diagram:
==== HOW A WEBSITE SENDS A FILE ====
______ ____ ______
/ . . \ GET /file [____] READ / |
| j | ======> [____] ======> | file |
\__===_/ <====== [____] <====== | |
user RESPONSE server |_______|
I am creating and login signup system using express js mysql and node js, so as soon as i click on submit button i get an error as :
Cannot POST /public/register-controller
my index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>SignUp</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="style.css" rel="stylesheet">
<link href="signup.css" rel="stylesheet">
</head>
<body>
<header class="masthead">
<div class="boards-menu"></div>
<div class="logo">
<h1><i class="fab fa-trello logo-icon" aria-hidden="true"></i>Trello</h1>
</div>
</header>
<section class="signup-login">
<form action="/public/register-controller" method="POST">
<div class="username">
<input type="text" placeholder="User Name" name="name"></input>
</div>
<div class="username">
<input type="email" placeholder="Email" name="eamil"></input>
</div>
<div class="username">
<input type="password" placeholder="Password" name="password"></input>
</div>
<div class="button-signup-login">
<button class="add-card-btn btn">Sign Up</button>
<a class="signup-navigator" href="login.html">already a
user?</a>
</div>
</form>
</section>
</body>
</html>
my config.js
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
user: 'trello',
password: 'trello',
database: 'trello'
});
connection.connect(function (err) {
if (!err) {
console.log("Database is connected");
} else {
console.log("Error while connecting with database");
}
});
module.exports = connection;
my index.js
var express = require("express");
var path = require('path');
var bodyParser = require('body-parser');
var connection = require('./config');
var app = express();
var authenticateController = require('./public/authenticate-controller');
var registerController = require('./public/register-controller');
var dir = path.join(__dirname, 'public');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(dir));
/* route to handle login and registration */
app.post('/api/register', registerController.register);
app.post('/api/authenticate', authenticateController.authenticate);
console.log(authenticateController);
app.post('/public/register-controller', registerController.register);
app.post('/public/authenticate-controller', authenticateController.authenticate);
app.listen(8012);
my register-controller.js
var connection = require('/home/codemymobile/study/trello/config');
var Cryptr = require('cryptr');
var express = require("express");
var cryptr = new Cryptr('myTotalySecretKey');
module.exports.register = function (req, res) {
var encryptedString = cryptr.encrypt(req.body.password);
var sql = 'insert into users(name, email, password) values ?';
var values = [[req.body.name, req.body.email, encryptedString]];
connection.query(sql, [values], function (err, result) {
if (err) throw err;
console.log("Number of records inserted: " + result.affectedRows);
res.status(200).send({ error: false, message: "User has been created successfully" });
});
};
my authenticate-controller.js
var Cryptr = require('cryptr');
cryptr = new Cryptr('myTotalySecretKey');
var connection = require('./../config');
module.exports.authenticate = function (req, res) {
var email = req.body.email;
var password = req.body.password;
connection.query('SELECT * FROM users WHERE email = ?', [email], function (error, results, fields) {
if (error) {
res.json({
status: false,
message: 'there are some error with query'
});
} else {
if (results.length > 0) {
decryptedString = cryptr.decrypt(results[0].password);
if (password == decryptedString) {
res.json({
status: true,
message: 'successfully authenticated'
});
} else {
res.json({
status: false,
message: "Email and password does not match"
});
}
}
else {
res.json({
status: false,
message: "Email does not exits"
});
}
}
});
};
so any help that why my file is not getting the path of register-contoller and i am getting this error, please help me out i am quite new to node and express
I think you have made a smaller mistake that is in the html form you are using eamil instead of email in name i.e name="eamil" instead of name="email", either change it here or else change the name you are calling in your js files
I am trying to understand where to locate the logic to send an email via a contact form in my Angular App (using angular-fullstack MEAN stack from Yeoman).
I can add the logic to send an email in the app.js file on the server side using nodemailer and sendgrid and everything works and an email is sent every time I refresh the server, however I am a little fuzzy on where to place the logic so that it only gets sent once the form is submitted and it hits the server side.
This is what the create action looks like on the Express JS side...
exports.create = function(req, res) {
Contact.create(req.body, function(err, contact) {
if(err) { return handleError(res, err); }
return res.json(201, contact);
});
};
Here is the code in app.js that is working, but obviously not in the right place...
var nodemailer = require('nodemailer');
var sgTransport = require('nodemailer-sendgrid-transport');
var options = {
auth: {
api_user: 'username', // 'SENDGRID_USERNAME' - Recommended to store as evn variables
api_key: 'password', // 'SENDGRID_PASSWORD'
}
};
var mailer = nodemailer.createTransport(sgTransport(options));
var email = {
to: 'sendto#email.com',
from: 'sendfrom#email.com',
subject: 'Test Email',
text: 'Awesome Email',
html: '<b>Bold and Awesome Email</b>'
};
mailer.sendMail(email, function(err, res) {
if (err) {
console.log(err)
}
console.log(res);
});
Coming from a rails background my initial thought is to stick the logic in the create action so that if the object is created successfully the email gets sent. Is this a correct way of thinking about it in this scenario...I am new to the MEAN stack.
Thanks for any help...
You need to create a route on the server that you can post form values to from Angular using $http.post.
The following lets you enter details in an Angular form. The form is then posted to Node where the req.body values are extracted and added email object. The email is then send by SendGrid.
SERVER.JS
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var dotenv = require('dotenv');
dotenv.load(); //load environment variables from .env into ENV (process.env).
var sendgrid_username = process.env.SENDGRID_USERNAME;
var sendgrid_password = process.env.SENDGRID_PASSWORD;
var sendgrid = require('sendgrid')(sendgrid_username, sendgrid_password);
var email = new sendgrid.Email();
var app = express();
app.use(bodyParser.json()); //needed for req.body
app.set('port', process.env.PORT || 3000);
app.use(express.static(__dirname + '/public'));
app.post('/email', function(req, res) {
email.addTo(req.body.to);
email.setFrom(req.body.from);
email.setSubject(req.body.subject);
email.setText(req.body.text);
email.addHeader('X-Sent-Using', 'SendGrid-API');
email.addHeader('X-Transport', 'web');
sendgrid.send(email, function(err, json) {
if (err) {
return res.send("Problem Sending Email!!!!");
}
console.log(json);
res.send("Email Sent OK!!!!");
});
});
var server = http.createServer(app);
server.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port') ) ;
});
INDEX.HTML
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<title></title>
<!-- CSS -->
</head>
<body ng-controller="MainCtrl">
<form name="emailForm">
<div class="group">
<input type="email" name="to" ng-model="email.to" ng-required="true">
<label>To</label>
</div>
<div>
<input type="email" name="from" ng-model="email.from" ng-required="true">
<label>From</label>
</div>
<div>
<input type="text" name="subject" ng-model="email.subject" ng-required="true">
<label>Subject</label>
</div>
<div>
<textarea ng-model="email.text" name="text" placeholder="Enter Text Here.."></textarea>
</div>
<button id="emailSubmitBn" type="submit" ng-click="submitEmail()">
Submit
</button>
</form>
<!-- JS -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
CLIENT SIDE APP.JS
angular.module('myApp', [])
.controller('MainCtrl', function($scope, $http) {
$scope.submitEmail = function() {
console.log("TEST");
//Request
$http.post('/email', $scope.email)
.success(function(data, status) {
console.log("Sent ok");
})
.error(function(data, status) {
console.log("Error");
})
};
});