there is required section in my form also I want to send successfully text after click of submit button. But problem is here when I click submit button, it shows successfully text no matter form is correct or not. Can you help me about that ? I am beginner :)
My react code here
import React, { Component } from "react";
export default class Form extends Component {
state = {
name: "",
surname: "",
phone: "",
email: "",
comments: "",
// isValid: true,
succesfully: ""
};
/* preventSending = async (e) => {
await this.setState({ [e.target.name]: e.target.value });
if (
this.state.name === "" ||
this.state.surname === "" ||
this.state.phone === "" ||
this.state.email === "" ||
this.state.comments === ""
) {
this.setState({ isValid: true });
} else {
this.setState({ isValid: false });
}
};*/
handleSubmit = (e) => {
this.setState({
succesfully: `${this.state.name} you have sent successfully `
});
};
render() {
return (
<div className="">
<form>
<label htmlFor="name">
Name :
<input
onChange={this.preventSending}
id="name"
name="name"
type="text"
required
/>
</label>
<br />
<label htmlFor="surname">
Surname :
<input
onChange={this.preventSending}
id="surname"
name="surname"
type="text"
required
/>
</label>
<br />
<label htmlFor="phone">
Phone :
<input
onChange={this.preventSending}
id="phone"
name="phone"
type="tel"
required
/>
</label>
<br />
<label htmlFor="email">
Email :
<input
onChange={this.preventSending}
id="email"
name="email"
type="email"
required
/>
</label>
<br />
<label htmlFor="textArea">
Comments :
<textarea
onChange={this.preventSending}
id="textarea"
name="comments"
required
/>
</label>
<br />
<button
type="submit"
// disabled={this.state.isValid}
onClick={this.handleSubmit}
>
Send details{" "}
</button>
</form>
<p>{this.state.succesfully}</p>
</div>
);
}
}
It says I have to add more details but I explained everything clear.
I have to go through your code and try to resolve the errors and get the proper output.
I see that you take the direct state object and update its value, I just corrected that part and also add one error flag in it, so that you can display one informational error message while you click the button without adding the data.
Apart from that, in your form, you take one button which has submit type.
As of now I simply update it with type=button, as type=submit will submit the form and redirect us to new URL.
Please let me know if it is useful to you or not.
here is my code
import React, { Component } from "react";
export default class Form extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
surname: "",
phone: "",
email: "",
comments: "",
// isValid: true,
succesfully: "",
error: "",
};
}
/* preventSending = async (e) => {
await this.setState({ [e.target.name]: e.target.value });
if (
this.state.name === "" ||
this.state.surname === "" ||
this.state.phone === "" ||
this.state.email === "" ||
this.state.comments === ""
) {
this.setState({ isValid: true });
} else {
this.setState({ isValid: false });
}
};*/
handleChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value,
});
}
handleSubmit = (e) => {
if (
this.state.name !== "" &&
this.state.surname !== "" &&
this.state.phone !== "" &&
this.state.email !== "" &&
this.state.comments !== ""
) {
// check valid email or not with regex
const regexp = /^([\w\.\+]{1,})([^\W])(#)([\w]{1,})(\.[\w]{1,})+$/;
let isValidEmail = regexp.test(this.state.email) ? true : false;
if (isValidEmail) {
this.setState({
succesfully: `${this.state.name} you have sent successfully `,
error: "",
});
} else {
this.setState({
succesfully: "",
error: "Please add proper email",
});
}
} else {
this.setState({
succesfully: "",
error: "Please add proper data",
});
}
};
render() {
return (
<div className="">
<form>
<label htmlFor="name">
Name :
<input
onChange={(e) => this.handleChange(e)}
id="name"
name="name"
type="text"
value={this.state.name}
required
/>
</label>
<br />
<label htmlFor="surname">
Surname :
<input
onChange={(e) => this.handleChange(e)}
id="surname"
name="surname"
type="text"
value={this.state.surname}
required
/>
</label>
<br />
<label htmlFor="phone">
Phone :
<input
onChange={(e) => this.handleChange(e)}
id="phone"
name="phone"
type="tel"
value={this.state.phone}
required
/>
</label>
<br />
<label htmlFor="email">
Email :
<input
onChange={(e) => this.handleChange(e)}
id="email"
name="email"
type="email"
value={this.state.email}
required
/>
</label>
<br />
<label htmlFor="textArea">
Comments :
<textarea
onChange={(e) => this.handleChange(e)}
id="textarea"
name="comments"
value={this.state.comments}
required
/>
</label>
<br />
<button
// type="submit" // use this while you want to submit your form
type="button" // I use button to call handleSubmit method and display message
// disabled={this.state.isValid}
onClick={this.handleSubmit}
>
Send details
</button>
</form>
<p>{this.state.succesfully}</p>
<p>{this.state.error}</p>
</div>
);
}
}
I see that the function prevent sending that you created should work except you misplaced the isValid argument:
function ValidateEmail(email)
{
if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email))
{
return true
}
return false
}
if (
this.state.name === "" ||
this.state.surname === "" ||
this.state.phone === "" ||
this.state.email === "" ||
this.state.comments === "" ||
!validateEmail(this.state.email)
) {
this.setState({ isValid: false });
} else {
this.setState({ isValid: true });
}
also uncomment disabled and isValid which should be false at the begginning:
// disabled={this.state.isValid}
// isValid = false
Related
Here is my code. The confirm state variable on line 34 will not change. Calling setConfirm from handleSubmit does not change it. I've attempted deliberately toggling it in dev tools, no effect. I've tried deliberately setting it to true in the code, and placing {confirm && <h1>TEST</h1>} at the top of the contact form. It doesn't render the h1, even when deliberately set to true. But {true && <h1>TEST</h1>} works just fine. It's as if the confirm variable doesn't even exist. Can someone shed some light on why this might be happening?
import { useState, useEffect } from 'react'
import styles from "./ContactAndBooking.module.css"
const ContactAndBooking = () => {
// Contact form values
const [contact, setContact] = useState({
name: null,
email: null,
phone: null,
reason: null,
message: null
})
// Booking form values
const [booking, setBooking] = useState({
name: null,
email: null,
phone: null,
date: null,
time: null,
description: null
})
// Store today's date, calendar selection minimum
const [minDate, setMinDate] = useState()
// Display contact form or booking form, switch on button press
const [typeContact, setTypeContact] = useState("contact")
// Flag invalid form values for validation alerts
const [validFlag, setValidFlag] = useState(true)
// Successful message confirmation flag
const [confirm, setConfirm] = useState(false)
// Keep track of today's date, booking calendar selection minimum
useEffect(()=> {
let today = new Date
let dd = today.getDate()
let mm = today.getMonth() + 1
let yyyy = today.getFullYear()
if (dd < 10)
dd = '0' + dd
if (mm < 10)
mm = '0' + mm
today = yyyy + '-' + mm + '-' + dd
setMinDate(today)
})
// Validate form values
const validate = () => {
// Track and return form validity, switch to false if any field fails
let isValid = true
// Check validity of contact form values
if (typeContact === "contact"){
// If no name, trigger invalid flag
if (!contact.name){
isValid = false
}
// If no email or email does not match regex, trigger invalid flag
if (!contact.email || !contact.email.match(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)){
isValid = false
}
// If phone number length is neither 10 nor 11 digits long, trigger invalid flag
if (!contact.phone || ![10,11].includes(contact.phone.split('-').join('').split('').length) || contact.phone.split('-').join('').split('').some(e => !'0123456789'.includes(e))){
isValid = false
}
// If no reason for contact is given, trigger invalid flag
if (!contact.reason){
isValid = false
}
// If message field is blank, trigger invalid flag
if (!contact.message){
isValid = false
}
}
// Check validity of booking form values
else if (typeContact === "booking"){
// If no name, trigger invalid flag
if (!booking.name){
isValid = false
}
// If no email or email does not match regex, trigger invalid flag
if (!booking.email || !booking.email.match(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)){
isValid = false
}
// If phone number length is neither 10 nor 11 digits long, trigger invalid flag
if (!booking.phone || ![10,11].includes(booking.phone.split('-').join('').split('').length)|| booking.phone.split('-').join('').split('').some(e => !'0123456789'.includes(e))){
isValid = false
}
// If no booking date is selected, trigger invalid flag
if (!booking.date){
isValid = false
}
// If no booking time is selected, trigger invalid flag
if (!booking.time){
isValid = false
}
// If no booking description is given, trigger invalid flag
if (!booking.description){
isValid = false
}
}
// set form validation alert flag on validation failure
!isValid ? setValidFlag(false) : setValidFlag(true)
return isValid
}
const handleSubmit = (e) => {
e.preventDefault()
setValidFlag(true)
if (validate()){
console.log("CONFIRMATION TRIGGERING...") // TESTING
// Trigger confirmation window
setConfirm(true) // NOT TRIGGERING
console.log("CONFIRMATION TRIGGERED") // TESTING
if (typeContact === "contact"){
// To be replaced with Axios request
console.log(contact)
}
else if (typeContact === "booking"){
// To be replaced with Axios request
console.log(booking)
}
}
// set form validation alert flag on validation failure
else {
setValidFlag(false)
console.log("SUBMISSION INVALID")
}
}
// Contact form view
const contactWindow = () => {
return (
<form onSubmit={e => handleSubmit(e)}>
{confirm && <h1>TEST</h1>}
<label className={styles.label} htmlFor="name">Name: </label>
<input
className={styles.input}
name="name"
type="text"
onChange={e => setContact({...contact, name: e.target.value})}
/>
<span className={!validFlag && !contact.name ? styles.warning : styles.warningHidden}>Please enter your name.</span>
<label className={styles.label} htmlFor="email">Email: </label>
<input
className={styles.input}
name="email"
type="email"
onChange={e => setContact({...contact, email: e.target.value})}
/>
<span className={
!validFlag && (!contact.email || !contact.email.match(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/))
? styles.warning
: styles.warningHidden
}>
Please enter a valid email address.
</span>
<label className={styles.label} htmlFor="phone">Phone: </label>
<input
className={styles.input}
name="phone"
type="text"
onChange={e => setContact({...contact, phone: e.target.value})}
/>
<span className={
!validFlag && (!contact.phone || ![10,11].includes(contact.phone.split('-').join('').split('').length) || contact.phone.split('-').join('').split('').some(e => !'0123456789'.includes(e)))
? styles.warning
: styles.warningHidden
}>Please enter a valid phone number.</span>}
<select
className={styles.select}
onChange={e => setContact({...contact, reason: e.target.value})}
defaultValue="Reason for contact"
>
<option className={styles.option} value="Reason for contact" disabled>Reason for contact</option>
<option className={styles.option} value="Business Inquiry">Business Inquiry</option>
<option className={styles.option} value="Ticket Sales">Ticket Sales</option>
<option className={styles.option} value="Other">Other</option>
</select>
<span className={!validFlag && !contact.reason ? styles.warning : styles.warningHidden}>Please select a reason for contact.</span>
<textarea
className={`${styles.textarea} ${styles.textareaContact}`}
placeholder="How can I help you?"
onChange={e => setContact({...contact, message: e.target.value})}
/>
<span className={!validFlag && !contact.message ? styles.warning : styles.warningHideen}>Please enter your message.</span>
<button className={styles.submit} role="submit">Submit</button>
</form>
)
}
// Booking form view
const bookingWindow = () => {
return (
<form onSubmit={handleSubmit}>
<label className={styles.label} htmlFor="name">Name: </label>
<input
className={styles.input}
name="name"
type="text"
onChange={e => setBooking({...booking, name: e.target.value})}
/>
<span className={!validFlag && !booking.name ? styles.warning : styles.warningHidden}>Please enter your name.</span>
<label className={styles.label} htmlFor="email">Email: </label>
<input
className={styles.input}
name="email"
type="email"
onChange={e => setBooking({...booking, email: e.target.value})}
/>
<span className={
!validFlag && (!booking.email || !booking.email.match(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/))
? styles.warning
: styles.warningHidden
}>
Please enter a valid email address.
</span>
<label className={styles.label} htmlFor="phone">Phone: </label>
<input
className={styles.input}
name="phone"
type="text"
onChange={e => setBooking({...booking, phone: e.target.value})}
/>
<span className={
!validFlag && (!booking.phone || ![10,11].includes(booking.phone.split('-').join('').split('').length)|| booking.phone.split('-').join('').split('').some(e => !'0123456789'.includes(e)))
? styles.warning
: styles.warningHidden
}>
Please enter a valid phone number.
</span>
<label className={styles.label} htmlFor="date">Select Date: </label>
<input
className={styles.datetime}
type="date"
name="date"
min={minDate}
onChange={e => setBooking({...booking, date: e.target.value})}
/>
<span className={!validFlag && !booking.date ? styles.warning : styles.warningHidden}>Please select a date for your event.</span>
<label className={styles.label} htmlFor="time">Select Time: </label>
<input
className={styles.datetime}
type="time"
name="time"
onChange={e => setBooking({...booking, time: e.target.value})}
/>
<span className={!validFlag && !booking.time ? styles.warning : styles.warningHidden}>Please select a time for your event.</span>
<textarea
className={`${styles.textarea} ${styles.textareaBooking}`}
placeholder="Please give a brief description of your event."
onChange={e => setBooking({...booking, description: e.target.value})}
/>
<span className={!validFlag && !booking.description ? styles.warning : styles.warningHidden}>Please describe your event.</span>
<button className={styles.submit} role="submit">Submit</button>
</form>
)
}
// Message confirmation window, triggered on successful validation and submission
const confirmWindow = () => {
return (
<div className={styles.confirmContainer}>
<h1 className={`${styles.confirmText} ${styles.confirmThankYou}`}>Thanks for the message!</h1>
<h3 className={`${styles.confirmText} ${styles.confirmSubThankYou}`}>I'll get back to you ASAP.</h3>
<button className={styles.confirmOkay} onClick={setConfirm(false)}>Okay</button>
</div>
)
}
return (
<div className={styles.container} id="contact">
<button
role="button"
className={`${styles.toggle} ${styles.toggleContact}`}
onClick={() => {
setTypeContact("contact")
setValidFlag(true)
}}
>
CONTACT
</button>
<button
role="button"
className={`${styles.toggle} ${styles.toggleBooking}`}
onClick={() => {
setTypeContact("booking")
setValidFlag(true)
}}
>
BOOKING
</button>
<br />
{typeContact === "contact" && contactWindow()}
{typeContact === "booking" && bookingWindow()}
{confirm && confirmWindow()}
</div>
)
}
export default ContactAndBooking
When you call setConfirm(false) in your onClick event, what you are actually saying is to run the setConfirm state update as soon as the page loads. What you want to do is create an arrow function in the onClick so that you are passing reference to a function that will be ran once the button is clicked.
<button className={styles.confirmOkay} onClick={() => setConfirm(false)}>Okay</button>
If you wanted to do more than just call setConfirm, you can create another function and call setConfirm inside of that, then you can just pass the new function as reference so that every time the button is clicked the setConfirm function gets called.
const handleConfirmUpdate = () => {
// do some stuff in here if you'd like
setConfirm(true);
}
<button className={styles.confirmOkay} onClick={handleConfirmUpdate}>Okay</button>
Notice that we are not calling the function, but rather passing a reference.
try changing line 273 from
<button className={styles.confirmOkay} onClick={setConfirm(false)}>Okay</button>
to
<button className={styles.confirmOkay} onClick={() => setConfirm(false)}>Okay</button>
then it appears to be working
I want to add a red border only if an input is empty. I couldn't find a way to "addClass" in React so I'm using state. Right now the code will add red border to all inputs, even if it has text.
State:
this.state = {
inputBorderError: false,
};
HTML/JSX:
<label>Name</label>
<input className={
this.state.inputBorderError ? 'form-input form-input-fail' : 'form-input'
} />
<label>Email</label>
<input className={
this.state.inputBorderError ? 'form-input form-input-fail' : 'form-input'
} />
<label>Message</label>
<textarea className={
this.state.inputBorderError ? 'form-input form-input-fail' : 'form-input'
} />
CSS:
.form-input-fail {
border: 1px solid red;
}
JS:
let inputFields = document.getElementsByClassName('form-input');
for (var i = 0; i < inputFields.length; i++) {
if (inputFields[i].value === '') {
this.setState({
inputBorderError: true,
});
}
}
I see the error in my code as it's basically setting the state to true anytime it finds an empty input. I think I may be approaching this incorrectly as there's only one state. Is there a solution based on my state approach, or is there another solution?
Right now, you have single state-value that affects all inputs, you should consider having one for each input. Also, your inputs are not controlled, it will be harder to record and track their values for error-handling.
It is good practice to give each input tag a name property. Making it easier to dynamically update their corresponding state-value.
Try something like the following, start typing into each input, then remove your text: https://codesandbox.io/s/nervous-feynman-vfmh5
class App extends React.Component {
state = {
inputs: {
name: "",
email: "",
message: ""
},
errors: {
name: false,
email: false,
message: false
}
};
handleOnChange = event => {
this.setState({
inputs: {
...this.state.inputs,
[event.target.name]: event.target.value
},
errors: {
...this.state.errors,
[event.target.name]: false
}
});
};
handleOnBlur = event => {
const { inputs } = this.state;
if (inputs[event.target.name].length === 0) {
this.setState({
errors: {
...this.state.errors,
[event.target.name]: true
}
});
}
};
handleOnSubmit = event => {
event.preventDefault();
const { inputs, errors } = this.state;
//create new errors object
let newErrorsObj = Object.entries(inputs)
.filter(([key, value]) => {
return value.length === 0;
})
.reduce((obj, [key, value]) => {
if (value.length === 0) {
obj[key] = true;
} else {
obj[key] = false;
}
return obj;
}, {});
if (Object.keys(newErrorsObj).length > 0) {
this.setState({
errors: newErrorsObj
});
}
};
render() {
const { inputs, errors } = this.state;
return (
<div>
<form onSubmit={this.handleOnSubmit}>
<label>Name</label>
<input
className={
errors.name ? "form-input form-input-fail" : "form-input"
}
name="name"
value={inputs.name}
onChange={this.handleOnChange}
onBlur={this.handleOnBlur}
/>
<label>Email</label>
<input
className={
errors.email ? "form-input form-input-fail" : "form-input"
}
name="email"
value={inputs.email}
onChange={this.handleOnChange}
onBlur={this.handleOnBlur}
/>
<label>Message</label>
<textarea
className={
errors.message ? "form-input form-input-fail" : "form-input"
}
name="message"
value={inputs.message}
onChange={this.handleOnChange}
onBlur={this.handleOnBlur}
/>
<button type="submit">Submit</button>
</form>
</div>
);
}
}
You are correct that there is only one state.
What you need to do is store a separate error for each input. one way to do this is with a set or array on state like state = {errors: []} and then check
<label>Name</label>
<input className={
this.state.errors.includes('name') ? 'form-input form-input-fail' : 'form-input'
} />
<label>Email</label>
<input className={
this.state.errors.includes('email') ? 'form-input form-input-fail' : 'form-input'
} />
} />
You should keep track of the input value in the state instead of checking for borderStyling state only.
Base on your code, you could refactor it to something like this:
// keep track of your input changes
this.state = {
inputs: {
email: '',
name: '',
comment: '',
},
errors: {
email: false,
name: false,
comment: false,
}
};
// event handler for input changes
handleChange = ({ target: { name, value } }) => {
const inputChanges = {
...state.inputs,
[name]: value
}
const inputErrors = {
...state.errors,
[name]: value == ""
}
setState({
inputs: inputChanges,
errors: inputErrors,
});
}
HTML/JSX
// the name attribut for your input
<label>Name</label>
<input name="name" onChange={handleChange} className={
this.errors.name == "" ? 'form-input form-input-fail' : 'form-input'
} />
<label>Email</label>
<input name="email" onChange={handleChange} className={
this.errors.email == "" ? 'form-input form-input-fail' : 'form-input'
} />
<label>Message</label>
<textarea name="comment" onChange={handleChange} className={
this.errors.comment == "" ? 'form-input form-input-fail' : 'form-input'
} />
And if you are probably looking at implementing it with CSS and js, you can try this article matching-an-empty-input-box-using-css-and-js
But try and learn to make your component reusable and Dry, because that is the beginning of enjoying react app.
[Revised]
I didn't figure out how to edit JSON data from a Put request.(it must be PUT request)
I created some inputs as you see and I need to find a way for updating/adding new credit-debit datas on JSON data differs by "to" and "from".
Also, if a "to" value added, it must decreased from total balance and if a "from" value added, it must be added to total balance.
I created a select box and an input for this (didin't connect between json and component)
My Updater component is as follows:
Component itself:
import React, { Component } from 'react';
import './Updater.scss';
import Axios from 'axios';
export default class Updater extends Component {
constructor(){
super();
this.state = {
amount: '',
description: '',
from: '',
to: '',
date: new Date()
}
}
onSubmitEdit = () => {
Axios.put('http://localhost:8080/api/balance/add',
{});
}
render() {
return (
<div className="updatercontainer">
<div className="updaterinputs">
<input className="amount" name="amount"
type="text" placeholder="Enter Amount"/>
<input className="description" name="description"
type="text" placeholder="Enter Description"/>
</div>
<div className="selectbox">
<select>
<option value="From">From</option>
<option value="To">To</option>
</select>
<input className="fromto" type="text"
name="fromto" placeholder="Enter From or To Name"/>
</div>
<div className="selectboxcontainer">
<div className="button-container">
<a href="#" onClick={this.onSubmitEdit}
className="button amount-submit">
<span></span>Update</a>
</div>
</div>
</div>
)
}
}
class Updater extends React.Component {
constructor() {
super();
this.state = {
amount: 0,
description: "",
_from: true,
_to: false,
date: new Date()
};
}
onAmountChange = e => {
this.setState({
amount: e.target.value
});
};
onDescriptionChange = e => {
this.setState({
description: e.target.value
});
};
onSelectTypeChange = e => {
console.log(e.target.value);
this.setState({
[e.target.value === "from" ? "_from" : "_to"]: true,
[e.target.value !== "from" ? "_from" : "_to"]: false
});
if(e.target.value !== "from" && (this.state.from != null || this.state.from !== "")) {
this.setState({
to: this.state.from,
from: null
});
} else if(e.target.value === "from" && (this.state.to != null || this.state.to !== "")){
this.setState({
from: this.state.to,
to: null
});
}
};
onFromToChange = (e) => {
this.setState({
[this.state._from ? "from" : "to"]: e.target.value
});
}
onSubmitEdit = () => {
Axios.put(
"https://httpbin.org/put",
{
...this.state,
},
{ headers: { "Content-Type": "application/json" } }
)
.then(response => {
// handle Response
})
.catch(err => {
// handle Error
});
};
render() {
return (
<div className="updatercontainer">
<div className="updaterinputs">
<input
onChange={this.onAmountChange}
className="amount"
name="amount"
type="text"
placeholder="Enter Amount"
/>
<input
onChange={this.onDescriptionChange}
className="description"
name="description"
type="text"
placeholder="Enter Description"
/>
</div>
<div className="selectbox">
<select onChange={this.onSelectTypeChange}>
<option value="from">From</option>
<option value="to">To</option>
</select>
<input onChange={this.onFromToChange} className="fromto" type="text"
name="fromto" placeholder="Enter From or To Name"/>
</div>
<div className="selectboxcontainer">
<div onClick={this.onSubmitEdit} className="button-container">
<a href="#" className="button amount-submit">
<span>Update</span>
</a>
</div>
</div>
</div>
);
}
}
Consider Reading More About Handling Inputs, Forms, Events
Working Sandbox!
you just need an onChange event to update the state based on the input values name
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
//On your inputs
<input
className="amount"
name="amount"
type="text"
placeholder="Enter Amount"
value={this.state.amount}
onChange={() => this.handleChange(e)}
/>
I am trying to build a contact form where an if else statement checks the validity of the email address entered, then with a nested if else checks whether the honeypot filed has a value and sends an ajaxj post request to an aws api gateway.
The ajax post runs without problem, but the outer else is always run.
Here the code:
import React from 'react'
import './style.scss'
const $ = require('jquery')
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email:'',
subject:'',
message:'',
honeypot:'',
result:'',
alertType:'',
formErrors:{
email:'',
name:'',
message:''
},
isFormValid:false,
emailValid:false,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target
const value = target.value
const name = target.name
this.setState({ [name]: value })
}
handleSubmit(event) {
event.preventDefault();
var URL = "https://someaddress/";
var form =this
var data = {
name: this.cleanInput(this.state.name.trim()),
email: this.cleanInput(this.state.email.trim()),
subject: this.cleanInput(this.state.subject.trim()),
message: this.cleanInput(this.state.message.trim()),
}
this.validateField('email',data.email)
data.message = "Bilgiler şunlar:\nAdı:"+data.name+"\nEmail Adresi: "+data.email+"\nKonu:"+data.subject+"\nMesaj:"+data.message
data.subject = "[Bestpet Web Sitesinden Doldurulan Form] "+data.subject;
data.email = "info#atlaspet.com.tr";
if(this.state.emailValid ===true){
if (this.state.honeypot=== ''){
$.ajax({
type: "POST",
url: URL,
dataType: "json",
contentType: "application/json",
data: JSON.stringify(data),
success: function(){
form.setState({name:'',email:'',message:'',subject:'',result:'Form başarıyla gönderildi.',alertType:'alert alert-success'})
},
error: function () {
// show an error message
form.setState({result: 'Sorunlar oluştu. Formu gönderemedik.',alertType:'alert alert-danger'});
},
});
} else {console.log("Hi there, I guess you are not human baby");}
} else { form.setState({result: 'Lütfen girmiş olduğunuz email adresini kontrol ediniz.',alertType:'alert alert-danger'})}
}
validateField(fieldName, value) {
let fieldValidationErrors = this.state.formErrors;
let emailValid = this.state.emailValid;
;
switch (fieldName) {
case 'email':
emailValid = value.match(/^([\w.%+-]+)#([\w-]+\.)+([\w]{2,})$/i);
fieldValidationErrors.email = emailValid ? true : false;
break;
default:
break;
}
this.setState({
formErrors: fieldValidationErrors,
emailValid: fieldValidationErrors.email
}, this.validateForm);
console.log(this)
}
validateForm() {
this.setState({ isFormValid: this.state.emailValid });
}
cleanInput(input){
var search = [
'<script[^>]*?>.*?</script>', // Strip out javascript
'<[/!]*?[^<>]*?>', // Strip out HTML tags
'<style[^>]*?>.*?</style>', // Strip style tags properly
'<![sS]*?--[ \t\n\r]*>', // Strip multi-line comments
]
var text = input
// console.log(search.length)
//var output = preg_replace($search, '', input);
for (let i = 0; i < search.length; i++) {
text = text.replace(new RegExp(search[i], 'gi'), '')
}
return text
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<div className={"col-md-12 "+this.state.alertType}>{this.state.result!=='' && this.state.result}</div>
<input name="honeypot" type="text" style={{display:"none"}} value={this.state.honeypot} onChange={this.handleChange}/>
</div>
<div className="form-group">
<div className="col-md-6">
<label>
Name:
{this.state.formErrors.name!=='' && <div className="col-md-12 alert alert-danger">'Sizinle iletişim kurabilmemiz için bir isim girmelisiniz'</div>}
<input name="name" type="text" value={this.state.name} className ="form-control required" onChange={this.handleChange} />
</label>
</div>
<div className="col-md-6">
<label>
email
<input type="text" name="email" className="form-control required" value={this.state.email} onChange={this.handleChange}/>
</label>
</div>
</div>
<div className="form-group">
<div className="col-md-12">
<label>
Subject
<input type="text" name="subject" className="form-control required" value={this.state.subject} onChange={this.handleChange}/>
</label>
</div>
</div>
<div className="form-group">
<div className="col-md-12">
<label>
Message
<textarea name="message" rows="6" className="form-control required" value={this.state.message} onChange={this.handleChange}/>
</label>
</div>
</div>
<div className="form-group">
<div className="col-md-12">
<input type="submit" value="Submit" className="btn btn-sm btn-block btn-primary"/>
</div>
</div>
</form>
);
}
}
export default ContactForm
The section of code I have problems with is in handleSubmit function.
Thanks for help in advance and a happy new year to all.
I have moved the validity check to handleChange function and it is now working as intended.
Thanks a lot!
I am new to React and this thing is confusing me a lot. I have root component that has an array and I am passing functions ADD and DELETE as props to the child component ui_forms. In the child component, I am taking input parameters and pushing or deleting from array depending on the button pressed. However, I cannot seem to perform push/delete operation more than once because I guess I am injecting the child component only once in the root component.
Is there by any chance a way to perform push or delete as many times a user wants by sending props only once?
Thank you
App.js
import FormsMap from './form_map';
class App extends Component {
state = {
maps : [
{'regno' : 'Karan', 'id' : 1},
{regno : 'Sahil', 'id' : 2},
{'regno' : 'Rahul', id : 4},
{regno : 'Mohit', id : 5},
{regno : 'Kartik', id : 3}
]
};
function_as_props(list1) {
console.log(this.state.maps);
let ninja = [...this.state.maps];
console.log(ninja);
ninja.push({"regno" : list1, "id" : Math.random()*10});
this.setState({
maps : ninja
});
console.log(ninja);
function_as_props1(name) {
let t = this.state.maps.indexOf(name);
let x = this.state.maps.splice(t,1);
console.log(x);
this.setState({
maps : x
});
console.log(this.state.maps);
}
}
render() {
const p = this.state.maps.map(list => {
return(
<div key={list.id}> {list.regno} </div>
);
})
return(
<FormsMap transpose = {this.function_as_props.bind(this)} traverse ={this.function_as_props1.bind(this)} /> <br />
);
}
}
export default app;
form_map.js
import React, { Component } from 'react';
class FormsMap extends Component {
state = {
name : null,
age : null,
hobby : null
};
changes(e) {
this.setState({
[e.target.id] : e.target.value
});
}
handle = (e) => {
e.preventDefault();
console.log(this.state);
this.props.transpose(this.state.name);
}
dels = (e) => {
this.setState({
[e.target.id] : e.target.value
});
}
del_button(e) {
e.preventDefault();
//console.log(this.state.name);
this.props.traverse(this.state.name);
}
render() {
return(
<React.Fragment>
<form onSubmit={this.handle}> {/* After entering all info, Press Enter*/}
<label htmlFor="labels"> Name : </label>
<input type="text" id="name" placeholder="Your name goes here..." onChange={this.changes.bind(this)} />
<label htmlFor="labels"> Age : </label>
<input type="text" id="age" placeholder="Your age goes here..." onChange={this.changes.bind(this)} />
<label htmlFor="labels"> Hobby : </label>
<input type="text" id="hobby" placeholder="Your hobby goes here..." onChange={this.changes.bind(this)} /> <br /><br />
<input type="submit" value="SUBMIT" /><br /><br />
</form>
<input type="text" id="name" placeholder="Enter name to delete..." onChange={this.dels} /> <button onClick={this.del_button.bind(this)}> DELETE </button>
</React.Fragment>
);
}
}
export default FormsMap;
Try this
App.js
import React, { Component } from "react";
import FormsMap from "./components/FormsMap";
class App extends Component {
constructor(props) {
super(props);
this.state = {
maps: [
{ regno: "Karan", id: 1 },
{ regno: "Sahil", id: 2 },
{ regno: "Rahul", id: 4 },
{ regno: "Mohit", id: 5 },
{ regno: "Kartik", id: 3 }
]
};
}
function_as_props(list1) {
let ninja = this.state.maps.concat({
regno: list1,
id: Math.random() * 10
});
this.setState({ maps: ninja });
}
function_as_props1(name) {
let x = this.state.maps.filter(
list => list.regno.toLocaleLowerCase() !== name.toLocaleLowerCase()
);
this.setState({
maps: x
});
}
render() {
return (
<React.Fragment>
{this.state.maps.map(list => <div key={list.id}>{list.regno}</div>)}
<FormsMap
transpose={this.function_as_props.bind(this)}
traverse={this.function_as_props1.bind(this)}
/>
</React.Fragment>
);
}
}
export default App;
FormsMap.js
import React, { Component } from "react";
class FormsMap extends Component {
state = {
name: null,
age: null,
hobby: null
};
changes(e) {
this.setState({
[e.target.id]: e.target.value
});
}
handle = e => {
e.preventDefault();
this.props.transpose(this.state.name);
};
dels = e => {
this.setState({
[e.target.id]: e.target.value
});
};
del_button(e) {
e.preventDefault();
this.props.traverse(this.state.name);
}
render() {
return (
<React.Fragment>
<form onSubmit={this.handle}>
{" "}
{/* After entering all info, Press Enter*/}
<label htmlFor="labels"> Name : </label>
<input
type="text"
id="name"
placeholder="Your name goes here..."
onChange={this.changes.bind(this)}
/>
<label htmlFor="labels"> Age : </label>
<input
type="text"
id="age"
placeholder="Your age goes here..."
onChange={this.changes.bind(this)}
/>
<label htmlFor="labels"> Hobby : </label>
<input
type="text"
id="hobby"
placeholder="Your hobby goes here..."
onChange={this.changes.bind(this)}
/>{" "}
<br />
<br />
<input type="submit" value="SUBMIT" />
<br />
<br />
</form>
<input
type="text"
id="name"
placeholder="Enter name to delete..."
onChange={this.dels}
/>{" "}
<button onClick={this.del_button.bind(this)}> DELETE </button>
</React.Fragment>
);
}
}
export default FormsMap;
This is the demo: https://codesandbox.io/s/xl97xm6zpo