I have a form like this that I created with context crud project. Here I want that if no changes have been made in the form, it should not be updated and a notification should be issued. How can I do this? Note: also, if any input is empty, do not submit. How can I do this without required the input. How can I fix these problems?
import React from "react";
import { NavLink } from "react-router-dom";
import { useContext, useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { GlobalContext } from "../../context/GlobalState";
import styles from "../ContactForm/Form.module.scss";
import { toast } from "react-toastify";
const EditContactForm = () => {
const { contacts, UPDATE_CONTACT } = useContext(GlobalContext);
const [selectedContact, setSelectedContact] = useState({
id: "",
name: "",
surname: "",
fatherName: "",
specialty: "",
email: "",
gender: "",
test:''
});
const history = useNavigate();
const { id } = useParams();
useEffect(() => {
const userId = id;
const selectedContact = contacts.find((user) => String(user.id) === userId);
if (selectedContact) {
setSelectedContact(selectedContact);
}
}, [id, contacts]);
function onSubmit(e) {
e.preventDefault();
if(selectedContact){
UPDATE_CONTACT(selectedContact);
console.log("new user edited:", selectedContact);
history("/contacts");
toast('updated')
}
else if(selectedContact===contacts){
toast('anything doesnt changed') // problem is there
}
}
const handleOnChange = (e) => {
setSelectedContact((selectedContact) => ({
...selectedContact,
[e.target.name]: e.target.value,
}));
};
const inputHandleChange = (e) => {
setSelectedContact({
...selectedContact,
[e.target.name]: e.target.checked ? e.target.id : "",
});
};
const selectOptions = [
{ label: "One", value: 1 },
{ label: "Two", value: 2 },
{ label: "Three", value: 3 },
];
const onChange = (e) => setSelectedContact({ ...selectedContact, [e.target.name]: e.target.value })
return (
<div className={styles.form}>
<form onSubmit={onSubmit}>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Name</label>
<div class="col-sm-8">
<input
class="form-control"
name="name"
required
value={selectedContact?.name ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Surname</label>
<div class="col-sm-8">
<input
class="form-control"
name="surname"
required
value={selectedContact?.surname ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>
Father Name
</label>
<div class="col-sm-8">
<input
class="form-control"
name="fatherName"
required
value={selectedContact?.fatherName ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Email</label>
<div class="col-sm-8">
<input
class="form-control"
name="email"
required
value={selectedContact?.email ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>
Specialty
</label>
<div class="col-sm-8">
<input
class="form-control"
name="specialty"
required
value={selectedContact?.specialty ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div className="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>position</label>
<div className="col-sm-8 d-flex justify-content-center align-items-center">
<select
onChange={onChange}
value={selectedContact.test}
name="test"
class="form-select"
aria-label="Default select example"
>
{selectOptions.map((item) => (
<option
key={item.value}
value={item.value}
>
{item.label}
</option>
))}
</select>
</div>
</div>
<div className="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Gender</label>
<div className="col-sm-8">
<div class="form-check form-check-inline ">
<input
class="form-check-input"
type="radio"
name="gender"
id="male"
checked={selectedContact.gender === "male"}
onChange={inputHandleChange}
/>
<label class="form-check-label">Male</label>
</div>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="radio"
name="gender"
id="female"
checked={selectedContact.gender === "female"}
onChange={inputHandleChange}
/>
<label class="form-check-label">Female</label>
</div>
</div>
</div>
<div className="mb-3 row d-flex justify-content-around">
<div class="form-check col-sm-11">
<input
class="form-check-input"
type="checkbox"
name="updatesNotification"
id="update"
checked={selectedContact.updatesNotification === "update"}
onChange={(e) =>
setSelectedContact({
...selectedContact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
/>
<label class="form-check-label" for="flexCheckDefault">
I want to be notified of updates
</label>
</div>
</div>
<div className={styles.buttons}>
<button type="submit" class="btn btn-primary">
Update a contact
</button>
<NavLink to="/contacts" className="btn btn-danger m-2">
Cancel
</NavLink>
</div>
</form>
</div>
);
};
export default EditContactForm;
import React, { useState } from "react";
import { useContext } from "react";
import { GlobalContext } from "../../context/GlobalState";
import { useNavigate } from "react-router-dom";
import { NavLink } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import styles from "../ContactForm/Form.module.scss";
import { toast } from "react-toastify";
import { Checkbox, Button, Form, Input, Select, Radio } from "antd";
const Form1 = () => {
const { ADD_CONTACT } = useContext(GlobalContext);
const [contact, setContact] = useState({
id: uuidv4(),
name: "",
surname: "",
fatherName: "",
specialty: "",
email: "",
gender: "",
updatesNotification: "",
test: "",
});
const { Option } = Select;
const { name, surname, fatherName, specialty, email } = contact;
let history = useNavigate();
const onSubmit = () => {
if (contact) {
ADD_CONTACT(contact);
history("/contacts");
console.log(contact);
toast.success("Contact successfully added");
}
else{
???
}
};
const selectOptions = [
{ label: "One", value: 1 },
{ label: "Two", value: 2 },
{ label: "Three", value: 3 },
];
return (
<>
<Form
onFinish={onSubmit}
className={styles.form}
name="myForm"
initialValues={{
remember: true,
}}
autoComplete="off"
labelCol={{
span: 2,
}}
wrapperCol={{
span: 16,
}}
>
<div className="row">
<Form.Item
label="Name"
rules={[{ required: true, message: "Please input your name!" }]}
>
<Input
placeholder="Enter Your Name"
value={name}
name="name"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
</div>
<Form.Item
label="Surname"
rules={[{ required: true, message: "Please input your surname!" }]}
>
<Input
placeholder="Enter Your Surname"
value={surname}
name="surname"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Father Name"
rules={[{ required: true, message: "Please input your surname!" }]}
>
<Input
placeholder="Enter Your FatherName"
value={fatherName}
name="fatherName"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Email"
rules={[{ required: true, message: "Please input your mail!" }]}
>
<Input
name="email"
placeholder="your mail"
value={email}
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Specialty"
rules={[{ required: true, message: "Please input your specialty!" }]}
>
<Input
name="specialty"
placeholder="your specialt"
value={specialty}
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item label='Category'>
<Select
onChange={(e)=>setContact({ ...contact, test : e })}
defaultValue='category'
// value={contact.test}
name="test"
style={{
width: 120,
}}
>
{selectOptions.map((item) => (
<Option key={item.value} value={item.value}></Option>
))}
</Select>
</Form.Item>
<Form.Item label="Gender">
<Radio.Group
onChange={(e) =>
setContact({
...contact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
name="gender"
rules={[{ required: true, message: "Please your gender!" }]}
>
<Radio
id="female"
value="Female"
checked={contact.gender === "female"}
>
Female
</Radio>
<Radio id="male" value="Male" checked={contact.gender === "male"}>
Male
</Radio>
</Radio.Group>
</Form.Item>
<Form.Item>
<Checkbox
name="updatesNotification"
checked={contact.updatesNotification === "update"}
id="update"
onChange={(e) =>
setContact({
...contact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
>
I want to be notified of updates
</Checkbox>
</Form.Item>
<div className={styles.buttons}>
<Button type="primary" htmlType="submit">
Add contact
</Button>
<NavLink to="/contacts">
<Button danger>Cancel</Button>
</NavLink>
</div>
</Form>
</>
);
};
export default Form1;
One way to check if two objects are equal is to transform them into string.
JSON.stringify(selectedContact) === JSON.stringify(contacts.find((user) => user.id === selectedContact.id))
For checking if one if the data is empty one way is using the method some, this method send true if one the item in an array match the condition.
if (Object.keys(selectedContact).some(key => !selectedContact[key])) {
alert('There are missing information')
}