Reactjs Object State Change Events in Form - reactjs

So I've got a basic form that I'm rendering and the component needs state. I would prefer for the state to be an object instead of a list of values so I can easily call JSON.stringify(stateObject). This would enable me to easily refactor into a more re-usable HOC later where I pass the state object definition & urls as a configuration.
Anyways, what happens is that every time I modify an input, it clears out the properties which were not changed and sets the property which was changed.
See initial entry below
I add input to a different input and it removes the first input and adds the second input. Notice that Facility Name is now cleared and address is now populated.
Below is the code which is doing this
import React, { useState } from "react";
import { Form, Row, Col, Button, Container } from "react-bootstrap";
function FacilitiesCreate() {
const [Name, setName] = useState("");//not ideal
const [Latitude, setLatitude] = useState("");//not ideal
const [Longitude, setLongitude] = useState("");//not ideal
const [Description, setDescription] = useState("");//not ideal
const [AddressLineOne, setAddressLineOne] = useState("");//not ideal
const [AddressLineTwo, setAddressLineTwo] = useState("");//not ideal
const [City, setCity] = useState("");//not ideal
const [State, setState] = useState("");//not ideal
const [ZipCode, setZipCode] = useState(""); //not ideal
const [Facility, setFacility] = useState({
Name: "",
Latitude: 0,
Longitude: 0,
Description: "",
AddressLineOne: "",
AddressLineTwo: "",
City: "",
State: "",
ZipCode: "",
}); //I want to be able to JSON.stringify this for my body post call :D see handleSubmit
const createFacilityEndpoint = "https://localhost:7113/api/facilities";
const handleSubmit = async (event) => {
event.preventDefault();
let response = await fetch(createFacilityEndpoint, {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(Facility),
});
if (response.ok) {
alert("YAY!");
}
};
return (
<Container>
<h2>Create New Facility</h2>
<p>facility name: {Facility.Name}</p>
<br></br>
<p>address: {Facility.AddressLineOne}</p>
<Form onSubmit={handleSubmit}>
<Row className="mb-3">
<Col>
<Form.Label>Location Name</Form.Label>
<Form.Control
type="text"
placeholder="Location's Name"
onChange={(e) => setFacility({ Name: e.target.value })}
/>
</Col>
<Col>
<Form.Label>Latitude</Form.Label>
<Form.Control
type="float"
placeholder="Enter Latitude"
onChange={(e) => setLatitude(e.target.value)}
/>
</Col>
<Col>
<Form.Label>Longitude</Form.Label>
<Form.Control
type="float"
placeholder="Enter Longitude"
onChange={(e) => setLongitude(e.target.value)}
/>
</Col>
</Row>
<Row className="mb-3">
<Col>
<Form.Label>Description</Form.Label>
<Form.Control
as="textarea"
rows={3}
placeholder="Enter Description"
onChange={(e) => setDescription(e.target.value)}
/>
</Col>
</Row>
<Form.Group className="mb-3" controlId="formGridAddress1">
<Form.Label>Address</Form.Label>
<Form.Control
placeholder="1234 Main St"
onChange={(e) => setFacility({ AddressLineOne: e.target.value })}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formGridAddress2">
<Form.Label>Address 2</Form.Label>
<Form.Control
placeholder="Apartment, studio, or floor"
onChange={(e) => setAddressLineTwo(e.target.value)}
/>
</Form.Group>
<Row className="mb-3">
<Form.Group as={Col} controlId="formGridCity">
<Form.Label>City</Form.Label>
<Form.Control
placeholder="Miami Beach"
onChange={(e) => setCity(e.target.value)}
/>
</Form.Group>
<Form.Group as={Col} controlId="formGridState">
<Form.Label>State</Form.Label>
<Form.Control
placeholder="FL"
onChange={(e) => setState(e.target.value)}
/>
</Form.Group>
<Form.Group as={Col} controlId="formGridZip">
<Form.Label>Zip</Form.Label>
<Form.Control
placeholder="33141"
onChange={(e) => setZipCode(e.target.value)}
/>
</Form.Group>
</Row>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</Container>
);
}
export default FacilitiesCreate;
So the above is kinda cool, except it keeps nuking the other properties in the Facility State object...

Change the following:
(e) => setFacility({ Name: e.target.value })
to:
(e) => setFacility((oldValue) => ({ ...oldValue, Name: e.target.value }))
There is an option with useState to provide a callback function to the set function. This callback gets the old value of the state as parameter, so you can use it for the new state you want to set.

Related

ReactJS | Consolidate Form onChange Handlers

So check out this one for more details on original problem: Reactjs Object State Change Events in Form
Now I'd really like to consolidate my handlers, I've ended up with a bunch of inline onChange handlers, which if I want to extract and re-use my code is not really acheivable unless I can consolidate them into a single handler. How would one go about consolidating these into a single function which can handle everything?
<Container>
<h2>Create New Facility</h2>
<p>facility name: {Facility.Name}</p>
<br></br>
<p>address: {Facility.AddressLineOne}</p>
<Form onSubmit={handleSubmit}>
<Row className="mb-3">
<Col>
<Form.Label>Location Name</Form.Label>
<Form.Control
type="text"
placeholder="Location's Name"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
Name: e.target.value,
}))
}
/>
</Col>
<Col>
<Form.Label>Latitude</Form.Label>
<Form.Control
type="float"
placeholder="Enter Latitude"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
Latitude: e.target.value,
}))
}
/>
</Col>
<Col>
<Form.Label>Longitude</Form.Label>
<Form.Control
type="float"
placeholder="Enter Longitude"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
Longitude: e.target.value,
}))
}
/>
</Col>
</Row>
<Row className="mb-3">
<Col>
<Form.Label>Description</Form.Label>
<Form.Control
as="textarea"
rows={3}
placeholder="Enter Description"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
Description: e.target.value,
}))
}
/>
</Col>
</Row>
<Form.Group className="mb-3" controlId="formGridAddress1">
<Form.Label>Address</Form.Label>
<Form.Control
placeholder="1234 Main St"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
AddressLineOne: e.target.value,
}))
}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formGridAddress2">
<Form.Label>Address 2</Form.Label>
<Form.Control
placeholder="Apartment, studio, or floor"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
AddressLineTwo: e.target.value,
}))
}
/>
</Form.Group>
<Row className="mb-3">
<Form.Group as={Col} controlId="formGridCity">
<Form.Label>City</Form.Label>
<Form.Control
placeholder="Miami Beach"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
City: e.target.value,
}))
}
/>
</Form.Group>
<Form.Group as={Col} controlId="formGridState">
<Form.Label>State</Form.Label>
<Form.Control
placeholder="FL"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
State: e.target.value,
}))
}
/>
</Form.Group>
<Form.Group as={Col} controlId="formGridZip">
<Form.Label>Zip</Form.Label>
<Form.Control
placeholder="33141"
onChange={(e) =>
setFacility((oldValue) => ({
...oldValue,
ZipCode: e.target.value,
}))
}
/>
</Form.Group>
</Row>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</Container>
Well, you can implement the hook that manages the form state and allows you to register new fields:
function useForm({ defaultValues = {} }) {
const [ values, setValues ] = useState(defaultValues);
const field = (name) => {
const onChange = (e) => {
setValues((current) => ({ ...current, [name]: e.target.value }));
};
const value = values[name];
return { name, onChange, value };
};
return { field, values };
}
Then apply it to the form
function FacilityForm() {
const { values, field } = useForm({});
const handleSubmit = () => {
console.log(values);
};
return (
<Form onSubmit={handleSubmit}>
<Form.Label>Location Name</Form.Label>
<Form.Control
{...field('location')}
type="text"
placeholder="Location's Name"
/>
<Form.Label>Latitude</Form.Label>
<Form.Control
{...field('latitude')}
type="text"
placeholder="Latitude"
/>
</Form>
);
}
This is a very simple implementation that may lack the features you might want to have (e.g validation, nested keys, etc.). I would recommend you consider the existing libraries for that. For example, react-hook-forms is very good for such purposes

Validation is not working for these and unable to write something in the forum

I am using this form from the react bootstrap. But when i am trying to validate it is not working. Can some one please help here and thanks in adavance.
but when i am trying to validate the username, email and phone, I am unable to do it also unable to write something in the forum, can some one please help me where i made exact error
import React, { useEffect, useState } from 'react'
import { Button, Col, Form, Row } from 'react-bootstrap';
const AddressValidation = () => {
const initialValues = { username: "", email: "", password: "" };
const [formValues, setFormValues] = useState(initialValues);
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const handleChange = (e) => {
const { name, value } = e.target;
setFormValues({ ...formValues, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
setFormErrors(validate(formValues));
setIsSubmit(true);
};
useEffect(() => {
console.log(formErrors);
if (Object.keys(formErrors).length === 0 && isSubmit) {
console.log(formValues);
}
}, [formErrors]);
const validate = (values) => {
const errors = {};
const regex = /^[^\s#]+#[^\s#]+\.[^\s#]{2,}$/i;
if (!values.username) {
errors.username = "Username is required!";
}
if (!values.email) {
errors.email = "Email is required!";
} else if (!regex.test(values.email)) {
errors.email = "This is not a valid email format!";
}
if (!values.username) {
errors.username= "usernameis required";
} else if (values.username.length < 4) {
errors.username= "username must be more than 4 characters and combination of 3 letters";
} else if (values.username.length > 10) {
errors.username= "username cannot exceed more than 10 characters";
}
return errors;
};
return (
<div className="container">
<pre>{JSON.stringify(formValues, undefined, 2)}</pre>
<Form onSubmit = { handleSubmit }>
<h1> Payment Validation Form</h1>
<Row className="mb-3">
<Form.Group as={Col} controlId="formGridUsername">
<Form.Label>User Name</Form.Label>
<Form.Control type="text" placeholder="Enter User Name" value={ formValues.username}
onChange = {handleChange}/>
</Form.Group>
<Form.Group as={Col} controlId="formGridEmail">
<Form.Label>Email</Form.Label>
<Form.Control type="email" placeholder="Enter email" value={ formValues.email}
onChange = {handleChange} />
</Form.Group>
<Form.Group as={Col} controlId="formGridPhone">
<Form.Label>phonenumber</Form.Label>
<Form.Control type="number" placeholder="Enter email" value={ formValues.phonenumber}
onChange = {handleChange} />
</Form.Group>
</Row>
<Form.Group className="mb-3" controlId="formGridAddress1">
<Form.Label>Address</Form.Label>
<Form.Control placeholder="1234 Main St" />
</Form.Group>
<Form.Group className="mb-3" controlId="formGridAddress2">
<Form.Label>Address 2</Form.Label>
<Form.Control placeholder="Apartment, studio, or floor" />
</Form.Group>
<Row className="mb-3">
<Form.Group as={Col} controlId="formGridCity">
<Form.Label>City</Form.Label>
<Form.Control />
</Form.Group>
<Form.Group as={Col} controlId="formGridState">
<Form.Label>State</Form.Label>
<Form.Select defaultValue="Choose...">
<option>Choose...</option>
<option>Stockholm</option>
<option>Mälmo</option>
</Form.Select>
</Form.Group>
<Form.Group as={Col} controlId="formGridZip">
<Form.Label>Zip</Form.Label>
<Form.Control />
</Form.Group>
</Row>
<Form.Group className="mb-3" id="formGridCheckbox">
<Form.Check type="checkbox" label="Check me out" />
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</div>
);
}
export default AddressValidation
You need to add the name property to your inputs. Otherweise you get an empty name property from event.target:
<Form.Control
name="username"
type="text"
placeholder="Enter User Name"
value={formValues.username}
onChange={handleChange}
/>
Your validation seems to work. When I try to submit, I can read the error messages in console:
{username: 'usernameis required', email: 'Email is required!'}

React Multiselect package is sending [object, Object] instead of key and value

I am trying to pass data in my Django back end from react front end. I am able to pass the data using some Multi-select from react. But the problem is I am sending label and value but when I try to print my data in front end and check the data what it is passing I got the result like [object Object] instead of [mylabel MyValue]
and I just want to pass the option value. I am new to react so don't know much about setState things. Can someone help me to do this?
Or any other easy way to pass multiple data in my API it would be much appreciated like I select HD and SD then in my backend I should get both value.
#This is my react code check the deliveryOption, setDeliveryOption
import axios from "axios";
import React, { useState, useEffect } from 'react'
import { LinkContainer } from 'react-router-bootstrap'
import { Table, Button, Row, Col, Form } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import FormContainer from '../components/FormContainer'
import { MultiSelect } from "react-multi-select-component";
import Select from 'react-select';
const UPLOAD_ENDPOINT = "http://127.0.0.1:8000/api/orders/create/products/";
const options = [
{ label: "HD 🍇", value: "HD" },
{ label: "SD 🥭", value: "SD" },
{ label: "DP 🍓", value: "DP" },
];
function VendorProductCreate() {
const [file, setFile] = useState(null);
const [name, setName] = useState("");
const [price, setPrice] = useState();
const [discount, setDiscount] = useState();
const [description, setDescription] = useState("");
const [subcategory, setSubcategory] = useState("");
const [countInStock, setCountInStock] = useState();
const [deliveryOption, setDeliveryOption] = useState([]);
// const [selected, setSelected] = useState([]);
const { userInfo } = useSelector((state) => state.userLogin);
const handleSubmit = async (event) => {
event.preventDefault();
const formData = new FormData();
formData.append("avatar", file);
formData.append("name", name);
formData.append("price", price);
formData.append("discount", discount);
formData.append("description", description);
formData.append("subcategory", subcategory);
formData.append("countInStock", countInStock);
formData.append("deliveryOption", deliveryOption);
// formData.append("selected", selected);
const resp = await axios.post(UPLOAD_ENDPOINT, formData, {
headers: {
"content-type": "multipart/form-data",
Authorization: `Bearer ${userInfo.token}`,
},
});
console.log(resp.status)
};
return (
<FormContainer>
<form onSubmit={handleSubmit}>
<br></br>
<Link to='/productlist/vendor'>
<Button
variant='outline-info'>Go Back</Button>
</Link>
<FormContainer>
<br></br>
<h1>Merchant Product Upload</h1></FormContainer>
<br></br>
<br></br>
<Form.Group controlId='name'>
<Form.Label><strong> Product Name </strong> </Form.Label>
<Form.Control
required
type='text'
onChange={(e) => setName(e.target.value)}
value={name}
// placeholder='Enter Name'
>
</Form.Control>
</Form.Group>
<br />
<Form.Group controlId='subcategory'>
<Form.Label>Choose a Category</Form.Label>
<Form.Select aria-label="Default select example"
required
type='text'
value={subcategory}
onChange={(e) => setSubcategory(e.target.value)}>
<option value="LPG Cylinder">LPG Cylinder</option>
<option value="LPG Gas">LPG Gas</option>
</Form.Select>
</Form.Group>
<br />
<Form.Group controlId='price'>
<Form.Label><strong>Price</strong> </Form.Label>
<Form.Control
required
type='number'
// placeholder='Enter Address'
onChange={(e) => setPrice(e.target.value)}
value={price}
>
</Form.Control>
</Form.Group>
<br />
<Form.Group controlId='discount'>
<Form.Label><strong> Set Discount (Optional) </strong> </Form.Label>
<Form.Control
type='number'
onChange={(e) => setDiscount(e.target.value)}
value={discount}
// placeholder='Enter Name'
>
</Form.Control>
</Form.Group>
<br />
<Form.Group controlId='countInStock'>
<Form.Label><strong> Stock </strong> </Form.Label>
<Form.Control
type='number'
onChange={(e) => setCountInStock(e.target.value)}
value={countInStock}
// placeholder='Enter Name'
>
</Form.Control>
</Form.Group>
<br />
<Form.Label><strong style={{marginLeft: 10}}>Product Picture</strong> </Form.Label>
<Form.Control
type='file'
id='image-file'
label='Choose File'
onChange={(e) => setFile(e.target.files[0])}
>
</Form.Control>
<br />
<Form.Group controlId='description'>
<Form.Label><strong> Description </strong> </Form.Label>
<Form.Control
required
type='text'
onChange={(e) => setDescription(e.target.value)}
value={description}
// placeholder='Enter Name'
>
</Form.Control>
</Form.Group>
<br />
{/* <Form.Group controlId='deliveryOption'>
<Form.Label>Choose a Delivery</Form.Label>
<Form.Select aria-label="Default select example"
required
multiple
type='checkbox'
onChange={(e) => setDeliveryOption(e.target.value)}>
<option value="HD">HD</option>
<option value="SD">SD</option>
</Form.Select>
</Form.Group>
<br /> */}
{/* <h1>Select Fruits</h1>
<pre>{JSON.stringify(selected)}</pre> */}
{/* <MultiSelect
options={options}
value={selected}
onChange={setSelected}
labelledBy="Select"
/> */}
<Select
isMulti
name="colors"
options={options}
className="basic-multi-select"
classNamePrefix="select"
value={deliveryOption}
onChange={setDeliveryOption}
/>
<br></br>
<FormContainer><FormContainer><FormContainer>
<Button variant='outline-primary' type="submit" className='btn-sm' >
Upload Product
</Button></FormContainer>
</FormContainer></FormContainer>
</form>
</FormContainer>
);
}
export default VendorProductCreate;
#this is backend code using Django rest
#api_view(['POST'])
#permission_classes([IsVendor])
def vendorCreateProduct(request):
data = request.data
user = request.user.vendor
print(data['deliveryOption'])
print(data['selected'])
product = Product.objects.create(
user=user,
name=data['name'],
old_price = data['price'],
discount = data['discount'],
image = data['avatar'],
countInStock = data['countInStock'],
subcategory = Subcategory.objects.get_or_create(name=data['subcategory'])[0],
description=data['description'],
delivery_option= DeliveryOption.objects.get_or_create(name=data['deliveryOption'])[0],
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
I just want to save some multiple choice field with multiple select option using Django and react if you know any other easy and good approach then share

How to add edit button and function in react.js

i want to share this question. So, i have a form which is designed by react-bootstrap. And also use React Hooks and React Function Component. I have a form which is add new form and delete form but i don't do edit form.
This is a return statement
return(
<Container>
<Row>
<Col>
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Label>Name</Form.Label>
<Form.Control ref = {firstname} type="text" placeholder="Name.." />
</Form.Group>
<Form.Group>
<Form.Label>Surname</Form.Label>
<Form.Control ref = {secondname} type="text" placeholder="Surname.." />
</Form.Group>
<Form.Group>
<Form.Label>Email address</Form.Label>
<Form.Control ref = {email} type="email" placeholder="E-Mail" />
<Form.Text> Please, Enter like "asd#asd.com"</Form.Text>
</Form.Group>
<Form.Group>
<Form.Label>Comment</Form.Label>
<Form.Control ref = {comment} as="textarea" rows={3} placeholder = "Notes :)"/>
</Form.Group>
<Button className = "btn-lg" onClick={handleSubmit} variant="success" type="submit">Submit</Button>
</Form>
</Col>
</Row>
{Formss}
</Container>
)
And then, These are the function of this return
const Formss = input.map((item , index) =>
{
return(
<Lists key = {index} item = {item} index = {index} deleteFunc={handleDelete}/>
)
}
)
const handleSubmit = (event) => {
event.preventDefault();
const name = firstname.current.value
const surname = secondname.current.value
const mail = email.current.value
const mycomment = comment.current.value
const data = {id:id(),
name : name,
surname : surname,
mail : mail,
mycomment : mycomment}
if(data.name && data.surname && data.mail && data.mycomment){
setInput([...input, data])
firstname.current.value = ""
secondname.current.value = ""
email.current.value = ""
comment.current.value =""
}else{
console.log("oopss")
}
}
I use ref hook for handleSubmit. So, How to add edit button and edit function?
To be able to edit data, and to save it in state you can do it as in provided example. Then in handleSubmit function you can process your data further:
import React from "react";
import { Container, Row, Col, Form, Button } from "react-bootstrap";
const App = () => {
const handleSubmit = (e) => {
e.preventDefault();
console.log(state);
};
const initialState = {
firstname: "",
secondname: "",
email: "",
comment: "",
};
const [state, setState] = React.useState(initialState);
const handleChange = ({ target: { value, name } }) => {
setState({ ...state, [name]: value });
};
return (
<Container>
<Row>
<Col>
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Label>Name</Form.Label>
<Form.Control
name="firstname"
value={state.firstname}
type="text"
placeholder="Name.."
onChange={handleChange}
/>
</Form.Group>
<Form.Group>
<Form.Label>Surname</Form.Label>
<Form.Control
name="secondname"
value={state.secondname}
type="text"
placeholder="Surname.."
onChange={handleChange}
/>
</Form.Group>
<Form.Group>
<Form.Label>Email address</Form.Label>
<Form.Control
value={state.email}
name="email"
type="email"
placeholder="E-Mail"
onChange={handleChange}
/>
<Form.Text> Please, Enter like "asd#asd.com"</Form.Text>
</Form.Group>
<Form.Group>
<Form.Label>Comment</Form.Label>
<Form.Control
name="comment"
value={state.comment}
as="textarea"
rows={3}
placeholder="Notes :)"
onChange={handleChange}
/>
</Form.Group>
<Button className="btn-lg" variant="success" type="submit">
Submit
</Button>
</Form>
</Col>
</Row>
</Container>
);
};
export default App;

How to add validation in Product add Form c- react component

I am doing Form for add product to firebase, but each click on the submit button, although it already has data or not, it still can add in Firebase. I would like to add validation to this case. How could I do that. I would like all file input cannot be left blank, and text file is always text not the number
const ProductForm = ({
products,
createProductRequest,
fetchProductRequest,
loading,
type }) => {
const [values, setValues] = useState({
image: "",
name: "",
price: 0,
description: "",
categoty: "",
});
const [imageAsFile, setImageAsFile] = useState();
useEffect(() => {
if (Object.keys(products).length) {
setValues(products);
}
}, [products]);
useEffect(() => {
if (type === "CREATE_PRODUCT_SUCCESS") {
fetchProductRequest();
}
}, [fetchProductRequest, type]);
const handleInputChange = (event) => {
// Create new product to update
const newPropdudct = {
...values,
[event.target.name]: event.target.value,
};
// Update new product for value
setValues(newPropdudct);
};
const handleFileChange = (event) => {
const image = event.target.files[0]
setImageAsFile(imageAsFile => (image))
console.log(image);
}
const onSave = () => {
createProductRequest(values, imageAsFile);
};
if (loading) {
return (
<Container>
<Loading />
</Container>
);
}
return (
<Container className="product-form">
<Form>
<Form.Group>
<Form.Group>
<Form.File
id="image"
label="Image choose"
value={values.image.name}
onChange={handleFileChange}
/>
</Form.Group>
</Form.Group>
<Form.Group controlId="name">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
placeholder="Enter product name"
value={values.name}
name="name"
onChange={handleInputChange}
>
</Form.Control>
</Form.Group>
<Form.Group controlId="categories">
<Form.Label>Categories</Form.Label>
<Form.Control
as="select"
name="category"
value={values.category}
onChange={handleInputChange}
>
{CATEGORIES.map((category, index) => (
<option key={index}>{category.name}</option>
))}
</Form.Control>
</Form.Group>
<Form.Group controlId="price">
<Form.Label>Price</Form.Label>
<Form.Control
type="number"
placeholder="Enter product price"
value={values.price}
name="price"
onChange={handleInputChange}
/>
</Form.Group>
<Form.Group controlId="description">
<Form.Label>Description</Form.Label>
<Form.Control
as="textarea"
rows="3"
name="description"
value={values.description}
onChange={handleInputChange}
/>
</Form.Group>
<Button btnText="Submit" size="btn-md" handleClick={onSave} />
</Form>
</Container>
);
};
export default ProductForm;
You may start by adding the required attribute to each form control for basic HMTL5 validation.
For more advanced validation logic, you can have this as your onSave content:
const onSave = (event) => {
let invalid = [];
['name', 'description', 'category'].forEach(key => {
if (values[key].match(/[0-9]+/))
invalid.push(key);
});
if (values.name.trim() === '')
invalid.push('name');
if (invalid.length !== 0) {
event.preventDefault();
// Whatever you want to do when the content is invalid
} else {
createProductRequest(values, imageAsFile);
}
};
With this snippet, you have the invalid fields in the invalid array variable.
You can also customize the validation logic.

Resources