import axios from "axios";
import React from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import { useForm } from "react-hook-form";
import { toast, ToastContainer } from "react-toastify";
import auth from "../../firebase.init";
const AddInventoryItems = () => {
const { register, handleSubmit } = useForm();
const [user] = useAuthState(auth);
const onSubmit = (data) => {
axios.post("http://localhost:5000/item", data).then((res) => {
const { data } = res;
if (data) {
toast("You have added a new item, Yeah!!!");
}
});
};
return (
<div className="row w-25 mx-auto">
<form
className="d-flex flex-column my-5 col-sm-12 col-md-6"
onSubmit={handleSubmit(onSubmit)}
>
<input
placeholder="Enter Name"
className="mb-2"
value={user.displayName}
type="text"
{...register("user name")}
required
/>
<input
placeholder="Enter Email"
className="mb-2"
type="email"
value={user.email}
{...register("email")}
/>
<input
placeholder="Image Url"
className="mb-2"
type="text"
{...register("image")}
/>
<input
placeholder="Item name"
className="mb-2"
{...register("name", { required: true, maxLength: 20 })}
/>
<input
placeholder="Item description"
className="mb-2"
{...register("description")}
/>
<input
placeholder="Item price"
className="mb-2"
type="number"
{...register("price", { min: 18, max: 99 })}
/>
<input
placeholder="Item quantity"
className="mb-2"
type="number"
{...register("quantity", { min: 18, max: 99 })}
/>
<input
placeholder="Supplier name"
className="mb-2"
{...register("supplier name")}
/>
<input
className="btn btn-outline-primary"
type="submit"
value="Add new item"
/>
</form>
<ToastContainer />
</div>
);
};
export default AddInventoryItems;
To make responsive form elements, you have to wrap all the inputs in form-group class and in their inputs you have to add class form-control
example:
<div class="form-group">
<label for=""></label>
<input type="email" class="form-control" />
</div>
take a look on Bootstrap documentation:
https://getbootstrap.com/docs/5.1/forms/overview/
Use form-control class in your form input field. So your form field will be responsive.
<form className="d-flex flex-column my-5 col-sm-12 col-md-6 form-control" onSubmit={handleSubmit(onSubmit)}>
You can also see bootstrap official documentation for more detail
Related
I am creating a CV Application project and I have a button that allows the user to Add Work Experience. When the user clicks the button a form pops up and they are able to fill the information out and click Submit.
I'm trying to make it so once the user hits Submit, the form div stays hidden until the user clicks Add Work Experience again. I've made something similar before in vanilla JS where I simply changed the forms class from display: block to display: none but that doesn't seem possible in React.
import React, { Component } from "react";
class WorkExperience extends Component {
render() {
const workExperience = [
{
title: "title",
company: "company",
location: "location",
description: "description",
},
];
return (
<>
<div id="content" className="content">
<h1 className="title">Work Experience</h1>
<div className="work-experience">
<p>Job Title: {workExperience[0].title}</p>
<p>Company: {workExperience[0].company}</p>
<p>Location: {workExperience[0].location}</p>
<p>Description: {workExperience[0].description}</p>
</div>
</div>
<button className="form-btn">+ Add Work Experience</button>
</>
);
}
}
export default WorkExperience;
And here is the form code I am currently using. This is the form I want to show/hide after clicking the Add Work Experience button shown above.
<form>
<label for="title">Job Title</label>
<input id="title" className="form-row" type="text" name="title" />
<label for="company">Company</label>
<input className="form-row" type="text" name="company" />
<label for="location">Location</label>
<input className="form-row" type="text" name="location" />
<label for="description">Job Description</label>
<textarea rows="4" cols="50" name="description"></textarea>
<button className="save">Save</button>
<button className="cancel">Cancel</button>
</form>
You can use an if statement or a ternary to return different jsx. That would look something like this. There are other ways as well, however this is a basic example of something you could do.
<>
{
shouldShow ?
(
<div id="content" className="content">
<h1 className="title">Work Experience</h1>
<div className="work-experience">
<p>Job Title: {workExperience[0].title}</p>
<p>Company: {workExperience[0].company}</p>
<p>Location: {workExperience[0].location}</p>
<p>Description: {workExperience[0].description}</p>
</div>
</div>
<button className="form-btn">+ Add Work Experience</button>
) : (
<form>
<label for="title">Job Title</label>
<input id="title" className="form-row" type="text" name="title" />
<label for="company">Company</label>
<input className="form-row" type="text" name="company" />
<label for="location">Location</label>
<input className="form-row" type="text" name="location" />
<label for="description">Job Description</label>
<textarea rows="4" cols="50" name="description"></textarea>
<button className="save">Save</button>
<button className="cancel">Cancel</button>
</form>
)
}
</>
Where shouldShow is what determines whether the form is showing or not.
The benefit to this is that if the form is showing, the other content is not added to the DOM and vice versa.
shouldShow would be a variable you could add to state, and when the button is clicked, you toggle the state variable, causing a re-render.
https://reactjs.org/docs/state-and-lifecycle.html
You could also choose to render styles depending on whether or not that component is showing, the key being that boolean state variable that is re-rendering the component.
Use Repeater Felilds to add User Work Experience. It's so easy to handle like this.
Repeater Component
import React from "react";
const Repeater = ({ inputFields, setInputFields }) => {
const handleFormChange = (index, event) => {
let data = [...inputFields];
data[index][event.target.name] = event.target.value;
setInputFields(data);
};
const removeFields = (index) => {
let data = [...inputFields];
data.splice(index, 1);
setInputFields(data);
};
return (
<div className="row">
{inputFields.map((input, index) => {
return (
<>
<div className="form-group col-sm-12 col-md-4 mb-3">
<div className="controls">
<input
type="text"
className="form-control inputset"
id="title"
placeholder="title"
name="title"
data-validation-required-message="This field is required"
aria-invalid="true"
required
value={input.title}
onChange={(event) => handleFormChange(index, event)}
/>
<div className="help-block" />
</div>
</div>
<div className="form-group col-sm-12 col-md-4 mb-3">
<div className="date-picker">
<input
type="text"
className="pickadate form-control inputset"
value={input.company}
onChange={(event) => handleFormChange(index, event)}
name="company"
id="pass"
data-validation-required-message="This field is required"
data-toggle="tooltip"
data-trigger="hover"
data-placement="top"
data-title="Date Opened"
data-original-title=""
required
/>
</div>
</div>
<div className="form-group col-sm-12 col-md-4 d-flex mb-3">
<input
type="text"
className="form-control inputset"
id="location"
placeholder="location"
name="location"
data-validation-required-message="This field is required"
aria-invalid="true"
required
value={input.location}
onChange={(event) => handleFormChange(index, event)}
/>
<input
type="text"
className="form-control inputset"
id="description"
placeholder="description"
name="description"
data-validation-required-message="This field is required"
aria-invalid="true"
required
value={input.description}
onChange={(event) => handleFormChange(index, event)}
/>
{inputFields.length === 1 ? null : (
<button
type="button"
className=" d-flex justify-content-center align-items-center ml-1 btn"
onClick={() => {
removeFields();
}}
>
<i className="uil-trash-alt" />
</button>
)}
</div>
</>
);
})}
</div>
);
};
export default Repeater;
Main Component
use these as states and pass the objects to the Repeater Component. First, the state is empty and when the user clicks on the button Add More Experience The files auto-show.
const [inputFields, setInputFields] = useState([
{ degree_title: "", institue: "", end_date: "" },
]);
const addFields = () => {
let newfield = { degree_title: "", institue: "", end_date: "" };
setInputFields([...inputFields, newfield]);
};
<Repeater
inputFields={inputFields}
setInputFields={setInputFields}
addFields={addFields} />
I wish this solution helps you :) Make sure to change the state object according to your requirements.
I am trying to send data to my contact form api through react but I am getting this problem
I tried to get input as a value to post through api when clicked on submit button but it is not working
error = the api should call like this https://edu.orgiance.com/api/contactus?secret=xxxxx-ac40-46a0-9c81-d48a1322f4bb&fname=test&email=test#test.com&mobile=8463274946&message=test
but it is calling like this
http://localhost:3000/?name=dfdfsd&email=dsffdsf%40gmail.com&phone=937285294&website=sxascsac&message=dscdscsfgcd#
My Code
import React from 'react';
const ContactForm = (props) => {
const { submitBtnClass } = props;
function handleClick() {
// Send data to the backend via POST
fetch('https://edu.orgiance.com/api/contactus?secret=f1794e34-ac40-46a0-9c81-d48a1322f4bb&fname=test&email=test#test.com&mobile=8463274946&message=', { // Enter your IP address here
method: 'POST',
mode: 'cors',
body: JSON.stringify(jsonData) // body data type must match "Content-Type" header
})
}
var jsonData = {
"contact": [
{
"fname": props.fname,
"email": props.email,
"mobile": props.phone,
"message": props.message
}
]
}
return (
<form id="contact-form" action="#">
<div className="row">
<div className="col-md-6 mb-30">
<input className="from-control" type="text" id="name" name="name" placeholder="Name" value={props.fname} required />
</div>
<div className="col-md-6 mb-30">
<input className="from-control" type="text" id="email" name="email" placeholder="E-Mail" value={props.email} required />
</div>
<div className="col-md-6 mb-30">
<input className="from-control" type="text" id="phone" name="phone" placeholder="Phone Number" value={props.phone} required />
</div>
<div className="col-md-6 mb-30">
<input className="from-control" type="text" id="website" name="website" placeholder="Your Website" required />
</div>
<div className="col-12 mb-30">
<textarea className="from-control" id="message" name="message" placeholder="Your message Here" value={props.message}></textarea>
</div>
</div>
<div className="btn-part" >
<button onClick={handleClick} className={submitBtnClass ? submitBtnClass : 'readon learn-more submit'} type="submit">Submit Now </button>
</div>
</form>
);
}
export default ContactForm;
You're code has a few issues:
jsonData never gets updated, because any update to a state or prop will rerender your function and therefore reinitialize jsonData
Any value that is set on an input or textarea requires an onChange handler. Without it, you can't even type anything into the respective element. See https://reactjs.org/docs/forms.html#controlled-components for more information.
To make your code work, change jsonData into a state that get's initialized with the props data. To make an easier example, I will use contact as state and got rid of the array:
import React, { useState } from "react";
const ContactForm = (props) => {
const { submitBtnClass, ...other } = props;
const [contact, setContact] = useState({
fname: "",
email: "",
mobile: "",
message: "",
...other
});
function handleClick() {
// Send data to the backend via POST
fetch(
"https://edu.orgiance.com/api/contactus?secret=f1794e34-ac40-46a0-9c81-d48a1322f4bb&fname=test&email=test#test.com&mobile=8463274946&message=",
{
// Enter your IP address here
method: "POST",
mode: "cors",
body: JSON.stringify(contact) // body data type must match "Content-Type" header
}
);
}
function setContactData(e) {
const name = e.currentTarget.name;
const value = e.currentTarget.value;
setContact((prev) => {
return {
...prev,
[name]: value
};
});
}
return (
<form id="contact-form" action="#">
<div className="row">
<div className="col-md-6 mb-30">
<input
className="from-control"
type="text"
id="name"
name="fname"
placeholder="Name"
value={contact.fname}
onChange={setContactData}
required
/>
</div>
<div className="col-md-6 mb-30">
<input
className="from-control"
type="text"
id="email"
name="email"
placeholder="E-Mail"
value={contact.email}
onChange={setContactData}
required
/>
</div>
<div className="col-md-6 mb-30">
<input
className="from-control"
type="text"
id="phone"
name="phone"
placeholder="Phone Number"
value={contact.phone}
onChange={setContactData}
required
/>
</div>
<div className="col-md-6 mb-30">
<input
className="from-control"
type="text"
id="website"
name="website"
placeholder="Your Website"
value={contact.website}
onChange={setContactData}
required
/>
</div>
<div className="col-12 mb-30">
<textarea
className="from-control"
id="message"
name="message"
placeholder="Your message Here"
value={contact.message}
onChange={setContactData}
></textarea>
</div>
</div>
{JSON.stringify(contact)}
<div className="btn-part">
<button
onClick={handleClick}
className={
submitBtnClass ? submitBtnClass : "readon learn-more submit"
}
type="submit"
>
Submit Now{" "}
</button>
</div>
</form>
);
};
const App = () => {
return <ContactForm message={"test"} />;
};
export default App;
I am creating an application where I am getting a parameter from a function and if the parameter equals true I would render a new route instead.
I know how to use react-router-dom as to render new routes you would use something like this
<Link to="/login">Login</Link>
But I don't know how to call it in a function.
function functionName(success){
if (success){
//What do I write here?
// Something like go to path="/login"
}
}
Thank you
(edit)
import { useContext, useState, useEffect } from "react";
import { AuthContext } from "../../Context Api/authenticationAPI";
import { FaUserPlus } from "react-icons/fa";
import { Link, useHistory } from "react-router-dom";
import Alerts from "./Alerts";
const Register = () => {
const history = useHistory();
const { addUser } = useContext(AuthContext);
const data = useContext(AuthContext).data;
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
useEffect(() => {
console.log(data);
if (data.success) {
history.push("/login");
}
}, [data]);
return (
<div className="row mt-5">
<div className="col-md-6 m-auto">
<div className="card card-body">
<h1 className="text-center mb-3">
<i>
<FaUserPlus />
</i>{" "}
Register
</h1>
<Alerts />
<form>
<div className="mb-2">
<label>Name</label>
<input
type="name"
id="name"
name="name"
className="form-control"
placeholder="Enter Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<div className="mb-2">
<label>Email</label>
<input
type="email"
id="email"
name="email"
className="form-control"
placeholder="Enter Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="mb-2">
<label>Password</label>
<input
type="password"
id="password"
name="password"
className="form-control"
placeholder="Create Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<button
onClick={(e) => {
e.preventDefault();
addUser({ name, email, password });
}}
className="btn btn-primary col-12"
>
Register
</button>
<p className="lead mt-4">
Have An Account? <Link to="/login">Login</Link>
</p>
</form>
</div>
</div>
</div>
);
};
export default Register;
import React from "react";
import { Link } from "react-router-dom";
import { FaSignInAlt } from "react-icons/fa";
const Login = () => {
return (
<div className="row mt-5">
<div className="col-md-6 m-auto">
<div className="card card-body">
<h1 className="text-center mb-3">
<i>
<FaSignInAlt />
</i>{" "}
Login
</h1>
<div className="mb-2">
<label>Email</label>
<input
type="email"
id="email"
name="email"
className="form-control"
placeholder="Enter Email"
/>
</div>
<div className="mb-2">
<label>Password</label>
<input
type="password"
id="password"
name="password"
className="form-control"
placeholder="Enter Password"
/>
</div>
<button className="btn btn-primary col-12">Login</button>
<p className="lead mt-4">
No Account? <Link to="/register">Register</Link>
</p>
</div>
</div>
</div>
);
};
export default Login;
You can make use of the history object and programmatically navigate using history.push()
import { useHistory } from 'react-router-dom'
const history = useHistory();
function functionName(success){
if (success) {
history.push('/login')
}
}
Reference
useHistory Hook
Objective:
Need to pre-fill the form if the user has address saved in the DB.
Issue:
I am passing down the address object (coming from backend for the logged in user). :
{
city: "CA"
line1: "testline1"
line2: "testline2"
phone: "7772815615"
pin: "1234"
state: "CA"
user: "5eea03a736b70722c83a7b63"
}
Though I am able to console log it, but I am unable to pre-populate it in the form (rendered by the child component)
Child Component
let addressFinalValue = {};
const addressValue = (e) => {
addressFinalValue[e.target.name] = e.target.value;
};
const propsAddress = props.address;
const [address, setAddress] = useState(propsAddress);
console.log(propsAddress); // < -- ABLE TO CONSOLE LOG IT
return (
<div>
<div className="modal-header ">
<h5 className="modal-title text-center">
{address ? 'Please enter your address' : 'Please confirm your address'}
</h5>
<button className="close" data-dismiss="modal" aria-label="close">
<span className="edit-order-button" aria-hidden="true">Edit order</span>
</button>
</div>
<div className="container my-4">
<form onSubmit={submitHandler}>
{error && <p className="login-error" style={{ color: "red" }}>{error}</p>}
<div className="form-group">
<input id="address-line-1" className="form-control" value={propsAddress.line1}
onChange={addressValue} name="line1" type="text" placeholder="Line 1" />
</div>
<div className="form-group">
<input id="address-line-2" className="form-control" value={propsAddress.line2}
onChange={addressValue} name="line2" type="text" placeholder="Line 2" />
</div>
<div className="form-group">
<input id="city" className="form-control" value={propsAddress.city}
onChange={addressValue} name="city" type="text" placeholder="City" />
</div>
<div className="form-group">
<input id="state" className="form-control" value={propsAddress.state}
onChange={addressValue} name="state" type="text" placeholder="State" />
</div>
<div className="form-group">
<input id="pin" className="form-control" value={propsAddress.pin}
onChange={addressValue} name="pin" type="text" placeholder="PIN" />
</div>
<div className="form-group">
<input id="phone" className="form-control" value={propsAddress.phone}
onChange={addressValue} name="phone" type="text" placeholder="Phone Number" />
</div>
<hr />
<button className="btn btn-success">Save Address & Continue</button>
</form>
</div>
</div> );
Is there something I am missing here? I don't know what it is.
I would achieve this using the following:
Make the child component a class with state. Pass the child component a populate prop, with the address values.
<ChildComponent populate={address} />
constructor(props){
this.state = {
...props.populate
}
}
handleAddressChange(e, addressItem){
this.setState({[addressItem]: event.target.value});
}
Then, in your form, set the value of each form item equal to the stateful address value. For example:
<div className="form-group">
<input id="address-line-1" className="form-control" value={this.state.line1}
onChange={(e) => handleAddressChange(e, 'line1')} name="line1" type="text" placeholder="Line 1" />
</div>
Make sure your onChange event handler is updating the child components this.state.address value using setState.
Checkout this file for more info: https://github.com/ccrowley96/grocerylist/blob/master/client/src/components/AddEditModal/AddEditModal.js
I do something very similar.
I'm trying to use bootstrap 4 to display an error of an input from a form.
Everything It's working but once I click the "SignUp" button with the empty form, no red error is display it. So the ""has-danger"" class from Bootstrap 4 doesn't work. I would like to know if the is any other way to user the error class from Bootstap 4.
import React from 'react';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import classnames from 'classnames';
class SignUpForm extends React.Component {
constructor(props) {
super(props);
this.state = {
firstname: '',
lastname: '',
username: '',
password: '',
email: '',
errors: {},
isLoading: false
}
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
this.setState({errors: {}, isLoading: true});
this.props.userSignUpRequest(this.state).then(() => {}, ({data}) => this.setState({errors: data, isLoading: false}));
}
render() {
const {errors} = this.state;
return (
<form onSubmit={this.onSubmit}>
<div className={classnames('form-group', {'has-danger': errors.firstname})}>
<label className="form-control-label">
First Name
</label>
<input value={this.state.firstname} onChange={this.onChange} type="text" name="firstname" className="form-control form-control-danger" id="inputDanger1"/> {errors.firstname && <span className="help-block">{errors.firstname}</span>}
</div>
<div className="form-group has-danger">
<label className="form-control-label">
Last Name
</label>
<input value={this.state.lastname} onChange={this.onChange} type="text" name="lastname" className="form-control form-control-danger"/> {errors.lastname && <span className="help-block">{errors.lastname}</span>}
</div>
<div className="form-group">
<label className="control-label">
Username
</label>
<input value={this.state.username} onChange={this.onChange} type="text" name="username" className="form-control"/> {errors.username && <span className="help-block">{errors.username}</span>}
</div>
<div className="form-group">
<label className="control-label">
Password
</label>
<input value={this.state.password} onChange={this.onChange} type="text" name="password" className="form-control"/> {errors.password && <span className="help-block">{errors.password}</span>}
</div>
<div className="form-group">
<label className="control-label">
Email
</label>
<input value={this.state.email} onChange={this.onChange} type="text" name="email" className="form-control"/> {errors.email && <span className="help-block">{errors.email}</span>}
</div>
<div className="text-left">
<small>By clicking Submit, I agree that I have read and accepted the
Terms and conditions
</small>
</div>
<div className="form-group mt-1">
<button disabled={this.state.isLoading} className="btn btn-primary btn-lg">Sign Up</button>
</div>
</form>
);
}
}
SignUpForm.propTypes = {
userSignUpRequest: PropTypes.func.isRequired
}
export default SignUpForm;