Now to pass form values from React to Node server - javascript

I have an EmailList component in react with a form that calls EmailServer.js 'NodeMailer' on the server. I am able to send emails with test subject and message defined in the MailServer.js file statically. How can I pass the subject and message as state to be used in NodeMailer.
EmailList Component
var EmailList = React.createClass({
getInitialState() {
return {
subject: '',
message: ''
}
},
subjectChange(e) {
this.setState({subject: e.target.value})
},
messageChange(e) {
this.setState({message: e.target.value})
},
render() {
return (
<div>
<div>
<Breadcrumb title={this.props.route.title + ' - ' + this.props.location.state.title} />
</div>
<div className='ui-outer'>
<h2 className='text-center'>Email List</h2>
<form action='../EmailServer.js'>
<div className="form-group">
<label htmlFor="subject">Subject</label>
<input type="text" name="subject" className="form-control" onChange={this.subjectChange} value={this.state.subject} />
</div>
<div className="form-group">
<label htmlFor="message">Message</label>
<textarea rows="8" name="message" className="form-control" onChange={this.messageChange} value={this.state.message} />
</div>
<button type="submit" className="btn btn-success">Submit</button>
</form>
</div>
</div>
)
}
})
EmailServer.js
var nodemailer = require('nodemailer');
// Create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport('smtps://user%40gmail.com:pass#smtp.gmail.com');
// Setup e-mail data with unicode symbols
var mailOptions = {
from: 'em#il.com',
to: 'test#email.com',
subject: 'Hello', // <----Pass Subject State HERE
text: 'Hello World', // <-----Pass Message state HERE
html: '<b>Hello World</b>' // <-----Pass Message State HERE
};
// Send email with defined transport object
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
return console.log(error);
}
console.log('Message Sent: ' + info.response);
});

If i got your issue correct, there might be a number of issues here.
You might want to design your code on server side to handle email sending with nodejs express server requested from client.
app.get('/sendemail', function(req, res) {here you go and read request posted data/json})
Where app is nodejs express server instance.
Let react handler to submit a request with one of async http clients (like axios or jquery).
sendEmail: function(e){
e.preventDefault();
$.post(
"/sendemail",{
email: this.state.email,
password: this.state.password,
first_name: this.state.first_name,
last_name: this.state.last_name
}, function(result){
//track result here
});
}
Set form to be submitted with react function:
<form onSubmit={this.sendEmail} >...</form>

Related

Is accessing DOM elements in "read-only" mode without Refs a React anti-pattern?

I can't figure out if Refs are necessary if my intention is just to check what's inside of the DOM elements, but not "writing" in them in any way.
I have this code in my React application, in which I have a EmailJS form that lets the user send a email to me. I wanted to put a check to make sure that the user would fill each and every input of the form. To do such a thing, the idea was to access, after its submission, the form stored in the DOM to check whether it was filled or not:
Contacts.js
// import statements
export default function Contacts()
{
let confirmation;
const [toSend, setToSend] = useState({
from_name: '',
to_name: '',
message: '',
reply_to: '',
confirm: null
});
const validateAndSend = () =>
{
let isValid = true;
let stop = false;
const elementList = document.querySelectorAll("input");
elementList.forEach( /* Controllo se sono stati compilati tutti i campi del form */
(e) => {
if (e.value === ("") && stop === false) /* Stop è per stampare solo un alert in caso di più campi vuoti */
{
alert("You must fill every field of the form!");
isValid = false;
stop = true;
}
}
);
if (isValid === true)
{
send(
'service_ID', /* SERVICE ID del servizio su EmailJS.com */
'template_ID', /* TEMPLATE ID del template in uso su EmailJS.com */
toSend,
'USER ID') /* USER ID su EmailJS.com */
.then( (response) => {
console.log("EmailJS server response:", response.status, response.text);
})
.catch( (err) => {
console.log('Error sending email: ', err);
});
confirmation = (<p id="confirm_message">Email sent successfully to website's administrator. You will be contacted at the email address you've just provided.</p>) ;
setToSend((prevState) => { return {...prevState, confirm: true }});
};
};
const handleChange = (e) =>
{
setToSend({ ...toSend, [e.target.name]: e.target.value })
};
return (
<div className="Contacts">
<NavBar />
<h1>Contact us!</h1>
{ confirmation }
<form id="contacts-form" onSubmit={(event) => { event.preventDefault(); } }>
<input type="text" name="from_name" placeholder="from name" value={toSend.from_name} onChange={handleChange} />
<input type="text" name="to_name" placeholder="to name" value={toSend.to_name} onChange={handleChange} />
<input type="text" name="message" placeholder="Your message" value={toSend.message} onChange={handleChange} />
<input type="text" name="reply_to" placeholder="Your email" value={toSend.reply_to} onChange={handleChange} />
<button type='submit' onClick={ validateAndSend }>Send</button>
</form>
<CustomFooter position="stay_fixed" />
</div>
);
}
So, the main question is: do I really need to call useRef and access the form with it even tho I don't have any intention to manually edit the DOM ?
Side problem: after the form is submitted, the paragraph stored in { confirmation } does not get displayed.
Any case where you can use refs or other methods is preferred above querying elements from the DOM. One of the exceptions being selecting an element outside of the React root element that is not prone to be removed.
In your case you don't need any Refs either as you can use the Event object from the submit event to extract everything you need from the form. One of the methods is by using a FormData constructor to extract key-value pairs from the form.
Like in your own example, loop over the values and check if they are empty.
If all values are filled in, convert the FormData object to an actual object and send your data.
I also took the liberty to tinker a bit with your component. I feel that using uncontrolled inputs is the way to go. That just leaves a single state isConfirmed to check if the form has been sent successfully. Based on that state, render your confirmation message.
const [isConfirmed, setIsConfirmed] = useState(false);
const validateAndSend = async (event) => {
event.preventDefault();
const formData = new FormData(event.target);
for (const value of formData.values()) {
if (value === '') {
alert("You must fill every field of the form!");
return; // Stop the function.
}
}
// Convert iterable object to actual object.
const toSend = Object.fromEntries([...formData]);
try {
const response = await send(
'service_ID', /* SERVICE ID del servizio su EmailJS.com */
'template_ID', /* TEMPLATE ID del template in uso su EmailJS.com */
toSend,
'USER ID' /* USER ID su EmailJS.com */
);
console.log("EmailJS server response:", response.status, response.text);
setIsConfirmed(true);
} catch (err) {
console.log('Error sending email: ', err);
}
};
return (
<div className="Contacts">
<NavBar />
<h1>Contact us!</h1>
{isConfirmed && (
<p id="confirm_message"> Email sent successfully to website 's administrator. You will be contacted at the email address you've just provided.</p>
)}
<form id="contacts-form" onSubmit={validateAndSend}>
<input type="text" name="from_name" placeholder="from name" />
<input type="text" name="to_name" placeholder="to name" />
<input type="text" name="message" placeholder="Your message" />
<input type="text" name="reply_to" placeholder="Your email" />
<button type='submit'>Send</button>
</form>
<CustomFooter position="stay_fixed" />
</div>
);

How to get data from url into post request?

Any help appreciated. I've got an app that pulls data from google books api. From each book page, the user is able to leave a review. The path to the review is /review/${isbn Number}. Each page has a path based on the isbn. The review routes work and I'm able to make the post request through insomnia/postman with no issues, I'm just having trouble with the front-end js in pulling the data from the input boxes to make the post request. I'm not sure if the issue is because the isbn being in the path. Below is my front-end javascript that I am unable to fix.
const newFormHandler = async (event) => {
event.preventDefault();
console.log("testing")
const description = document.querySelector('#description').value;
const reviewTitle = document.querySelector('#reviewTitle').value;
const isbn = window.location.search
if (description) {
const response = await fetch(`api/review/${isbn}`, {
method: 'POST',
body: JSON.stringify({ description, reviewTitle }),
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
document.location.reload();
} else {
alert('Failed to create review');
}
}
};
document
.querySelector('.form-group')
.addEventListener('submit', newFormHandler);
My form is below:
<div class="col form-group">
<div class ="card reviewCard" style = "background-color:#fcf8f3; color: #65625e;">
<form id="blog-form">
<div>
<label for="reviewTitle">Review Title</label>
<input
value="{{title}}"
id="reviewTitle"
name="reviewtitle"
placeholder="Enter Review Title"
type="text"
required="required"
class="form-control"
data-bv-notempty="true"
data-bv-notempty-message="The title cannot be empty"
/>
</div>
<div>
<label for="review">Review</label>
<textarea
id="description"
name="review"
cols="40"
rows="10"
required="required"
class="form-control"
>{{description}}</textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
And here is my route that works fine with insomnia, no issues.
router.get('/review/:id', async (req, res) => {
try {
const isbn13 = req.params['id'];
const reviewData = await Review.findAll({ where: {
isbn:isbn13
},
include: [
{
model: User,
attributes: ['name'],
}
]
})
const reviews = reviewData.map((review) => review.get({ plain:true}));
// console.log(isbn13);
res.render('review', {
isbn: isbn13, reviews:reviews
});
} catch (err) {
console.log(err)
}
});
Any help appreciated. I tried to pull in the isbn number from the path, but with no success. I think I have it formatted wrong somehow.
First console log your req
You should see the body containing some data.
In a get request the they are arguments in the URL.
In a Psot request they are in the body of the request.

Can't figure out how to make a function for creating new users into the database

I am new to working with databases. I've been trying to create a login/register webpage using only HTML, Js and MongoDB in my codes in order to practice. I have successfully made a function for login, yet I've been struggling to create a function for registering using the Fetch API.
I am aware that my register code is used rather for a login function, but I used it as a template for the sign up one.
I'd appreciate it if anyone can help me fix the register function using Fetch() in order to not give me 401 and to be able to add the new user's email and password to my database. Thank you.
const btnAccount = document.querySelector('.account .submit')
btnAccount.addEventListener('click', event => {
event.preventDefault()
const email = emailAccount.value
const pass = passAccount.value
const pass2 = pass2Account.value
if (email && pass && pass2) {
if (pass === pass2) {
// The data i wish to add to my mongoDB users database:
const account = {
strategy: "local",
email : emailAccount.value,
password: passAccount.value
}
fetch('http://localhost:3030/authentication', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(account)
}).then(response => {
return response.json()
}).then(result => {
console.log(result)
document.forms[1].reset();
})
.catch(err => {
// If I got some errors regardings the DB or in the code itself:
console.log('eroare:', err)
alert(`Something's wrong. I can feel it!`)
})
}
else {
// Passwords not the same:
alert('Parolele nu coincid!')
}
}
else {
// Not all fields written:
alert('Completeaza bah campurile...')
}
})
<main>
<form class="account">
<div>
<label for="email">Email:</label>
<input required type="email">
</div>
<div>
<label for="password">Password:</label>
<input required type="password" class="password">
</div>
<div>
<label for="password2">Verify Password:</label>
<input type="password" class="password2">
</div>
<div>
<button class="submit">Create new account</button>
</div>
<div>
I already have an account
</div>
</form>
<button class="fetchItems">Load ITEMS</button>
<div class="output"></div>
</main>

Reactjs and Stripe: show success and error messages on submit

I am working on a payment system with Stripe on Reactjs.
I want to be able to display Success or Error messages but I am still new to React and I'm not sure where the code should be placed.
Success message: for when the payment is successful.
Error message: if there was some problem with the payment.
I also want to show the activation code they receive as a response, once the token is created. Like this:
{this.state.code && Your activation code (code)is: {this.state.code} and it is valid for {this.state.subscription_days} days.
But it does not work.
class CheckoutForm extends Component {
constructor(props) {
super(props);
this.state = {
complete: false,
referrer: '',
email: '',
amount: '',
};
this.submit = this.submit.bind(this);
}
componentDidMount() {
console.log(this.props);
let referrer = this.props.match.params.referrer; // url - added route to index.js
if (referrer) {
console.log(referrer);
this.setState({ referrer, });
}
// let amount = this.state.amount;
// document.getElementById('get3months').addEventListener('click', amount._handleAmount);
}
// user clicked submit
submit(ev) {
ev.preventDefault(); // prevent default submission and refreshing the page
this.props.stripe.createToken() // which elements to tokenize
.then(response => {
console.log('Received Stripe token:', response.token);
axios.post('http://10.250.57.37:8000/subscriptions/codes/pay/',
{
token: response.token,
amount: this.state.amount,
email: this.state.email,
referrer: this.state.referrer, // rn name or empty string, filip
},
{
'Content-Type': 'application/json', // header
}
)
.then(response => {
console.log(response);
});
})
.catch(error => {
console.log(error);
});
}
render() {
if (this.state.complete) return <p>Purchase Complete!</p>;
return (
<div className="checkout-form">
<PrimeHeading
heading={this.props.heading}
subheading={this.props.subheading}
/>
<p>Would you like to complete the purchase?</p>
<form onSubmit={this.submit} style={{ minHeight: 300, }}>
<label>
Email
<input
id="email"
name="email"
type="email"
placeholder="Enter your email"
required
onChange={this._handleEmailChange.bind(this)}
value={this.state.email}
/>
</label>
{/* <label>
Referral
<input
id="referrer"
name="referrer"
type="text"
placeholder="Enter your friends' usernames"
required
/>
</label> */}
<CheckoutCardSection />
<Button
// label="Pay" {this.state.amount} "DKK"
onClick={this.submit}
type="button"
size="medium"
backgroundColor="#43ddb1"
color="white"
noShadow
/>
</form>
{this.state.code && <div>Your activation code is: {this.state.code} and it is valid for {this.state.subscription_days} days.</div>}
</div>
);
}
_handleEmailChange(event) {
let email = event.target.value;
this.setState({ email, });
}
}
Let me know if you need more explanation. Help is MUCH appreciated!
In the code that you are showing, you should set a new state in either the then or catch callbacks. You can have some extra properties in your component's state to achieve this.
...
this.state = {
complete: false,
referrer: '',
email: '',
amount: '',
code: null,
subscription_days: null,
error: null,
};
...
And then, you would set it like this:
...
.then(response => {
console.log('Received Stripe token:', response.token);
axios.post('http://10.250.57.37:8000/subscriptions/codes/pay/',
{
token: response.token,
amount: this.state.amount,
email: this.state.email,
referrer: this.state.referrer, // rn name or empty string, filip
},
{
'Content-Type': 'application/json', // header
}
)
// Use the appropiate property in your response to set the values.
// Note that I'm using destructuring assignment
.then(({ code, subscription_days })=> {
this.setState({
code,
subscription_days
});
});
})
.catch(error => {
this.setState({
error: `Your error message.`//Maybe error.message?
});
});
...
Finally, I'd recommend to pull out your network call code from the component to a separate module and just return the response. It'd make your component code more readable.

Need help getting my nodemailer to work

I have been trying to set up nodemailer with my static site. I am having trouble getting require to work at the moment. I know I am doing something wrong - I just need another set of eyes to assist.
HTML:
<form name="betaForm" action="/betaForm" method="post">
<div class="form-group" >
<label for="contactName" style="float:left;">Contact Name</label>
<input type="test" name="contactName" value="" class="form-control" id="contactName" >
</div>
<div class="form-group">
<label for="practiceName" style="float:left;">Practice Name</label>
<input type="test" name="practiceName" value="" class="form-control" id="practiceName">
</div>
<div class="form-group">
<label for="phone1" style="float:left;">Phone</label>
<input type="test" name="phone1" value="" class="form-control" id="phone1">
</div>
<div class="form-group">
<label for="email1" style="float:left;">Email</label>
<input type="email" name="email1" value="" class="form-control" id="email1" >
</div>
<button type="submit" value="Send" class="btn btn-default">Submit</button>
</form>
SERVER.JS
var express=require('express');
var nodemailer = require("nodemailer");
var app = express();
app.get('/',function(req,res){
res.sendfile('www/index.html');
});
app.listen(3000,function(){
console.log("Express Started on Port 3000");
});
SENDMAIL.JS
var app = require('express');
var nodemailer = require('nodemailer');
app.get('/betaForm', routes.betaForm);
app.post('/betaForm', function (req, res) {
var mailOpts, smtpTrans;
//Setup Nodemailer transport, I chose gmail. Create an application-specific password to avoid problems.
smtpTrans = nodemailer.createTransport('SMTP', {
service: 'Gmail',
auth: {
user: "test#gmail.com",
pass: "password"
}
});
//Mail options
mailOpts = {
from: req.body.contactName + ' <' + req.body.email1 + '>', //grab form data from the request body object
to: 'test#gmail.com',
subject: ' beta contact form',
text: req.body.contactName,
};
smtpTrans.sendMail(mailOpts, function (error, response) {
//Email not sent
if (error) {
res.render('betaForm', { title: ' beta contact', msg: 'Error occured, message not sent.', err: true, page: 'contact' })
}
//Yay!! Email sent
else {
res.render('betaForm', { title: ' beta contact', msg: 'Message sent! Thank you.', err: false, page: 'contact' })
}
});
});
ROUTES.JS
var exports = module.exports = {};
exports.betaForm = function(req, res){
res.render('betaForm', { title: 'beta contact form', page: '/#beta' })
};
Sorry I'm not allowed to write comments.
Do you use the bodyparser?

Categories