I have an input field where the user enters a location, once the submit button is pressed, I can capture the data that the user entered as newLocation. However, I need to send this data to the back-end server and I am not sure how. I guess one way is to use axios.post and axios.get - but I am not quite sure how to implement that. See both front-end and back-end code below:
Front-end:
import store from "../src/store";
import axios from "axios";
const RenderButton = () => {
async function captureText() {
const locationName = document.getElementById("locationName");
let newLocation = locationName.value;
store.dispatch({ type: "locationUpdate", payload: newLocation });
}
return (
<div id="submit">
<h2>Enter Location</h2>
<input type="text" id="locationName" />
<button id="submitButton" onClick={captureText}>
Submit Location
</button>
</div>
);
};
export default RenderButton;
Back-end:
const path = require("path");
const axios = require("axios");
const app = express();
app.use("/dist", express.static(path.join(__dirname, "dist")));
app.use("/public", express.static(path.join(__dirname, "public")));
app.get("/", async (req, res, next) =>
res.sendFile(path.join(__dirname, "index.html"))
);
Axios would not be needed on the backend. You just need to set up a route in express, just like the / one that returns the html. It can take request parameters such as form data. Something like this:
app.get('/endpoint', function (req, res) {
console.log(req.body)
})
See for formdata parsing: https://stackoverflow.com/a/38763341/13357440
Also: https://expressjs.com/en/guide/routing.html
As for the frontend, many options exist that can send a request and get a response without redirecting. XMLHttpRequest (ajax) is one of the more popular ones. https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started#step_3_%E2%80%93_a_simple_example
Related
I'm making a MERN application. I'm fairly new to it, so I'm trying to make everything based on what I know without looking much stuff up, because if I follow tutorials too much I don't remember stuff. Anyway, I've got a component that sends the registration information to the database and everything there is okay. Now I'm trying to check the login.
When I make the "GET" request to a route that I named "/check", nothing happens. If I change it to a "POST" request, things work. Shouldn't it be a "GET" request though since I'm trying to get information from the database?
The Node file:
const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const bcrypt = require('bcrypt');
const application = express();
application.use(express.json());
application.use(express.urlencoded({ extended: true }));
const port = process.env.PORT || 8080;
mongoose.connect(process.env.PASSWORD)
.then(console.log('Database connected'))
.catch(error => console.log(error));
const db = mongoose.connection;
application.get('/', (request, response) => {
response.send('Hello World');
});
application.post('/post', (request, response) => {
db.collection('data').insertOne({
name: request.body.username,
password: bcrypt.hashSync(request.body.password, 10),
}).then(console.log('Submission done'));
console.log('POST made');
response.redirect('/');
});
application.get('/check', (request, response) => {
db.collection('data').findOne({
name: request.body.username,
password: bcrypt.compareSync(
request.body.password,
bcrypt.hashSync(request.body.password, 10)
),
});
console.log('The request went through');
response.redirect('/');
});
application.listen(port, () => {
console.log('Listening here...');
});
The React file:
import React from 'react';
export const Login = () => {
return (
<>
<h1 className="text-center">Login</h1>
<div className="row">
<div className="col"></div>
<div className="col text-center">
<form action="/check" method="GET">
<label for="username" name="username">Username: </label>
<input name="username" className="h4" />
<label for="password" name="password">Password: </label>
<input type="password" name="password" className="h4" />
<button>Submit</button>
</form>
</div>
<div className="col"></div>
</div>
</>
);
};
There is difference between the "GET" and "POST" of HTML form element and "GET" and "POST" of node.js .
From Node.js perspective, you can save/send data to database with both POST and GET. However, the situtation is different for form element.
If you use "GET" on the form element, then form will submit all input data to the URL. And on the node.js side, you will need to use req.query to get data on the url, not req.body
So, in your code, you are using "GET" for the Form element but on the node.js file, you are using req.body. This shouldn't work.
Even if you make it work with req.query, the situation will still be totally unsafe, as you openly showing the passwords on the URL.
For more info, on html form attributes, this link can be useful. https://www.w3schools.com/html/html_forms_attributes.asp
you are sending username and password to the server so you should to use POST method
So, I am using Node.js with express to run a server and make a calculator. After that, I downloaded body-parser, to get the access of the numbers the user inputs and use it to calculate the result, but for some reason whenever I try to log one of the numbers on console, just to make sure that it works, it doesn't get logged.
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.get('/', (req, res) => {
res.sendFile(`${__dirname}/index.html`);
})
app.post('/', (req, res) => {
console.log(req.body);
res.send('Thanks for the information');
})
app.listen(3000, () => console.log('Server Started'));
Your form will look something like this
<form id="post-form" action="/your/post/url" method="POST">
<div class="form-control">
<label for="title">Number</label>
<input type="number" name="number" id="number">
</div>
<button type="submit">
Submit
</button>
</form>
Or in your script tag, you can do something like this.
with this approach, the form gets submitted without reload
// Note: Optional approach (without reloading the page)
// Just above HTML only code also works perfectly fine
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const number= document.getElementById('number')
document.getElementById('post-form').addEventListener('submit', (e) => {
e.preventDefault();
axios
.post('/your/post/url', { number: number.value })
.then((res) => {
//handle response here
})
.catch((err) => { //handle err here});
});
<script>
then in you express app you can do
app.post('/you/post/url/', (req,res,next) => {
// this is how you accces title from you form
// here title will hold value "Value Here"
const { number} = req.body
//calculate here
number = number * number + number
// then send the response
res.send(`calculated number: ${number}`)
});
I have made basic web apps whereby data is sent via HTTP parameters. However, I am trying to send data from client-side that contains an array (a list of ingredients for a recipe) and eventually, hopefully user uploaded image (but not worried about that for now). For this I know I need to use AJAX. I have spent hours trying to get it to work but for some reason, no POST request is being sent. The user inputs are fairly basic but here's a snippet:
<label for="method"> Method </label>
<textarea id="method" name="method">method here</textarea>
</br>
<p> add ingredients </p>
<input name="ingredient" id="ingredient" placeholder="add ingredient">
<input name="quantity" id="quantity" placeholder="#"><button id="addIngBtn" type="button">Add</button><br>
<button type="submit">submit</button>
<p> Ingredients:</p>
<ul id="ingredientListUL">
I use JQUERY to allow users to append as many ingredients as they want to the list:
$(document).ready(() => {
$("#addIngBtn").click(() => {
let ingredient = $("#ingredient").val();
let quantity = $("#quantity").val();
$("#ingredient").val(""); //reset ingredient input
$("#quantity").val("");
$("ul").append(
"<li>" + ingredient + " - " + quantity + "</li>"
);
});
})
Ingredients are built into an array and then added to a new recipe object which is the data I want to send to my server:
var ingredients = [];
$("#ingredientListUL li").each((index, element) =>
ingredients.push($(element).text())
)
var recipe = {
name: $("#name").val(),
image: $("#image").val(),
oneLiner: $("#oneLiner").val(),
method: $("#method").val(),
ingredients: ingredients
}
So far so good. I presume I am doing something wrong with these next parts. Here's the AJAX post request:
$.ajax({
url: "http://localhost:5000/recipes",
type: "POST",
dataType: "json",
data: recipe,
contentType: "application/json",
complete: function () {
console.log("process complete");
},
success: function (data) {
console.log(data);
console.log("process success");
},
error: function () {
console.log(err);
}
})
And here's my server info:
// express setup
const express = require("express");
const app = express();
const port = 5000;
// set templating engine to EJS
app.set('view engine', 'ejs');
// import route files
const recipeRoutes = require("./routes/recipes")
app.use("/recipes", recipeRoutes);
// body parser
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
//--
// BASIC ROUTES
//--
app.get("/", (req, res) => res.render("landing"));
// Port
app.listen(port, () => console.log(`Server starting on port ${port}!`));
All routes, are stored in a recipe routes file, which contains the post route for this request:
// default "/" route is really "/recipes" as defined in main server file.
router.post("/", (req, res) => {
console.log(req.body.recipe);
})
The problem is that nothing appears to be sent to, or received by my server according to network tab. Even when I try to send something like:
$.post("http://localhost:5000/recipes", { test: "test" })
What am I doing wrong? Thanks.
The contentType property does not work that way. It indicates if it is URL encoded, as a multipart message, etc. Try removing it.
According to: https://api.jquery.com/jquery.ajax/ :
"If you explicitly pass in a content-type to $.ajax(), then it is
always sent to the server (even if no data is sent)"
I am trying to make a simple post request to Mongo Db Atlas using Node.js, Express.js and Mongoose.js. I fill out the form and send the request but it just keeps loading, no erros, nothing. ANyone have any ideas?
//Require assets
const express = require('express');
const app = express();
const mongoose = require('mongoose');
let port = 3000;
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const MongoClient = require('mongodb').MongoClient;
const uri = 'mongodb+srv://michael:<PASSWORD-GOES-HERE>#around-town-vsisv.mongodb.net/admin';
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
const collection = client.db('around_town_db').collection('events');
// perform actions on the collection object
client.close();
});
mongoose.Promise = global.Promise;
var eventSchema = mongoose.Schema({
eventName: String,
})
var eventData = mongoose.model('Event', eventSchema);
//Load index page using endpoint
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
//Post using endpoint
app.post('/addevent', (req, res) => {
var userData = {
eventName: req.body.eventName
}
new eventData(userData)
.save()
.then(res => {
res.send('item saved to database');
})
.catch(err => {
res.status(400).send('unable to save to database');
});
});
//Listen on port 3000
app.listen(port, () => {
console.log('Server listening on port ' + port);
});
Below is a simple form for submitting the post request. Any ideas on what I am missing?
<!DOCTYPE html>
<html>
<head>
<title>Add a local event</title>
</head>
<body>
<div class="app">
<h1>Add an event</h1>
<form method="post" action="/addevent">
<label>Enter event Name</label><br>
<input type="text" name="eventName" placeholder="Enter event name..." required>
<input type="submit" value="Add Event">
</form>
</div>
</body>
</html>
OK, so it looks like you have two problems. First, you're not letting Mongoose itself connect to your database, and second you're overwriting the response variable. If you note your .then() callback in the userData.save() promise chain, you're calling that result variable 'res' as well as the response variable 'res' from the route callback.
To fix the first problem, somewhere in your app startup, one time call (instead of your current MongoClient code)
mongoose.connect(uri)
You can also use mongoose.createConnection() if you want more fine-grained control over the connection, or need to make multiple connections to different databases.
Second problem, your post handler should look like this:
//Post using endpoint
app.post('/addevent', (req, res) => {
var userData = {
eventName: req.body.eventName
}
new eventData(userData)
.save()
.then(result => { // note the use of a different variable name
res.send(result); // also, you generally want to send *something* down that lets the user know what was saved. Maybe not the whole object, but this is illustrative and the client will at least need to know something (e.g. the id) to refer to the object by in the future.
})
.catch(err => {
res.status(400).send('unable to save to database');
});
});
Unrelated to your problem, but most folks write Express APIs in a RESTful manner. If you want to follow that convention, then your routes should look more like this:
GET /events // list the events
GET /events/:eventId // get a single event by ID
POST /events // add a new event
PUT /events/:eventId // update an existing event
DELETE /events/:eventId // remove an event
Try something like follow:
app.post('/addevent', (req, res) => {
var userData = new eventData({
eventName: req.body.eventName
})
userData.save()
.then(res => {
res.send('item saved to database');
})
.catch(err => {
res.status(400).send('unable to save to database');
});
});
I've found docs teaching on how to implement Twilio on server-side using Node, however, I couldn't find an end-end example where I can send a SMS coming from my client app.
Can anyone tell me what the implementation would look like to send a post custom SMS from client to server?
Disclaimer my server file is named as app.js and my client file is named as index.js
**1- This is what I have currently setup on my app.js
const express = require('express');
const app = express();
const path = require('path');
const twilio = require('twilio');
const bodyParser = require('body-parser');
//JSON DATA
const guests= require('./public/data/Guests');
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static('public'));
//SET PORT
app.set("port", process.env.PORT || 3000);
//GET JSON DATA
app.get('/data', function(req, res) {
Promise.all([guests])//combine requests into one object
.then(([guests]) => {
res.send({guests});
});
});
//CATCHALL
app.get("/*", function(req,res){
let file = req.params[0] || "/views/index.html";
res.sendFile(path.join(__dirname, "/public/", file));
});
//LISTEN ON PORT
app.listen(app.get("port"), function(){
console.log("Listening on port: " , app.get("port"));
});
let client = new twilio('xxxxxxxxxx', 'xxxxxxxxxxxxx');
app.post('/sms', (request, result) => {
const message = request.body.message;
client.messages.create({
to: +1847820802492359,
from: +8475302725792530 ,
body: message
}).then(() => {
// message sent successfully, redirect to the home page.
res.redirect('/');
}).catch((err) => {
console.error(err);
res.sendStatus(400);
});
});
-2 am trying to process a dynamic message in my index.js. The code works on the DOM properly, it is just the SMS with Twilio that isn't posting the message to the server
$(function() {
$.ajax({
type: "GET",
url: "/data",
success: res => {
//console.log(res);
handleMessage(res);
},
error: err => console.log(err)
});
//message method
let handleMessage = (res) => {
const getFirstName = res.guests.map(name => name.firstName);
//populate drop-down select
let handleSelect = () => {
//adds first names to select dropDown
$.each(getFirstName, function(i, value) {
$('#selectName').append($('<option>').text(value).attr('value', value));
});
};
handleSelect();
let handleSubmit = () => {
$("#form").submit(function(e) {
e.preventDefault();
let name = $('#selectName').val();
let greetGuest = `Welcome ${name}!`;
console.log(greetGuest);
//append to Dom
$('.showMessage').append(`<div class="newMessage"><span>${greetGuest}</span></div>`);
});
};
handleSubmit()
};
});
-3 HTML form
<form id="form" action="/sms" method="POST">
<label>
<label for=selectName>Guest
<select id="selectName" class="select " name="sms">
</select>
</label>
</label>
<input type="submit" value="send" class="btn btn-success" />
</form>
Am I having an asynchronicity issue here?
Twilio developer evangelist here.
I can give you a basic example here, which should give you a good idea of how to achieve this. I'll start with the server side, which you already have the basics of.
Firstly, I would recommend you use a POST request rather than a GET, simply because GETs can be easily repeated by users or cached by proxies. I assume you are using Express as the web application server. You will also need the body-parser module to read the data that we send from the client side.
const Twilio = require('twilio');
const express = require('express');
const bodyParser = require('body-parser');
const app = new express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static('public'));
const twilio = new Twilio(YOUR_ACCOUNT_SID, YOUR_AUTH_TOKEN);
app.post('/messages', (request, result) => {
const message = request.body.message;
twilio.messages.create({
to: TO_NUMBER,
from: FROM_NUMBER,
body: message
}).then(() => {
// message sent successfully, redirect to the home page.
res.redirect('/');
}).catch((err) => {
console.error(err);
res.sendStatus(400);
});
});
app.listen(3000);
This sets up a server which is serving static files from a public directory and then has one endpoint, POST to /messages, that sends a message.
We now need to create the client side. I shall do this in HTML only for simplicity. You need a form that will POST to the /messages endpoint with, in this case, a single field for the message. I've included a textarea to write the message in and a button to submit the form. If you save this as index.html in the public directory where you run the application from then it should work.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Send a message!</title>
</head>
<body>
<h1>Send a message!</h1>
<form action="/messages" method="POST">
<label for="message">What would you like to send?</label>
<textarea name="message" id="message"></textarea>
<button type="submit">Send!</button>
</form>
</body>
</html>
Let me know if that helps at all.
Update
So you're looking to make the request to the server using Ajax so your page doesn't reload and you can display a different message. Your current form seems to have removed the message textarea that I added, I'll put it back in again. I assume you also want to send the message to whichever guest you are welcoming at the time, but I don't know how that works in your system, so I'm going to avoid that for now and hopefully you can sort it out.
So, if you update your form to something like this:
<form id="form" action="/sms" method="POST">
<label>
<label for=selectName>Guest
<select id="selectName" class="select " name="sms">
</select>
</label>
</label>
<label for="message">Message</label>
<textarea id="message" name="message"></textarea>
<input type="submit" value="send" class="btn btn-success" />
</form>
Then you need to add to your JavaScript a way to actually submit the form (since you are preventing the submission with e.preventDefault().
const $form = $('#form');
$form.submit(function(e) {
e.preventDefault();
let name = $('#selectName').val();
let greetGuest = `Welcome ${name}!`;
console.log(greetGuest);
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: $form.serialize(),
success: function(data) {
console.log("The message has been sent");
},
error: function() {
console.error("The message couldn't be sent");
console.error(...arguments);
}
})
//append to Dom
$('.showMessage').append(
`<div class="newMessage"><span>${greetGuest}</span></div>`
);
});
In this case we are hooking into the callback for the submit event to make a new $.ajax request to the form's action, using the method (POST), and including the form data (which we get from $form.serialize()). We then setup success and error callbacks as you've done at the top of the function.
Let me know if this helps.