How can I do to display a new row with empty fields Name, Type, Email for Inviteds section if I click on the +Add new invite ?
For now I have only the button...
export default function App() {
...
let handleSubmit = async (e) => {
e.preventDefault();
try {
let res = await fetch("", {
method: "POST",
body: JSON.stringify({
location: location,
...
})
});
let resJson = await res.json();
if (res.status === 200) {
setLocation("");
...
} else {
setMessage("Some error occured");
}
} catch (err) {
console.log(err);
}
};
return (
<div className="flex flex-col">
...
<div className="mt-10 mb-3 h-6 text-md uppercase font-bold leading-8 text-gray-500">
People
</div>
<button>+Add new invite</button>
<form onSubmit={handleSubmit}>
<span >
Names:
</span>
<input
type="text"
value={invitedName}
placeholder="Names"
onChange={(e) => setInvitedName(e.target.value)}
/>
</form>
</div>
);
}
Here the picture to get the idea :
The invited values should be an array of invitee objects, each with the name, age, email, and location properties. When adding a new participant add a new invitee object. Map the invited array to an array of the field inputs.
Use generated GUIDs to identify which invitee you are editing.
Example:
import { v4 as uuidV4 } from "uuid";
...
const [invited, setInvited] = useState([
{
id: uuidV4(),
age: "",
email: "",
location: "",
name: ""
}
]);
const updateInvitee = (id) => (e) => {
const { name, value } = e.target;
setInvited((invitees) =>
invitees.map((invited) =>
invited.id === id
? {
...invited,
[name]: value
}
: invited
)
);
};
const addInvitee = () => {
setInvited((invitees) =>
invitees.concat({
id: uuidV4(),
age: "",
email: "",
location: "",
name: ""
})
);
};
...
<div className="mt-10 mb-3 h-6 text-md uppercase font-bold leading-8 text-gray-500">
People
</div>
<button type="button" onClick={addInvitee}>
+Add new participant
</button>
<form onSubmit={handleSubmit}>
{invited.map(({ age, email, id, location, name }) => (
<div key={id}>
<label className="mr-3 h-6 text-md font-bold leading-8 text-gray-500">
Names:
<input
type="text"
value={name}
placeholder="Names"
name="name"
onChange={updateInvitee(id)}
/>
</label>
<label className="mr-3 h-6 text-md font-bold leading-8 text-gray-500">
Age:
<input
type="text"
value={age}
placeholder="Age"
name="age"
onChange={updateInvitee(id)}
/>
</label>
<label className="mr-3 h-6 text-md font-bold leading-8 text-gray-500">
Location:
<input
type="text"
value={location}
placeholder="Location"
name="location"
onChange={updateInvitee(id)}
/>
</label>
<label className="mr-3 h-6 text-md font-bold leading-8 text-gray-500">
Email:
<input
type="text"
value={email}
placeholder="Email"
name="email"
onChange={updateInvitee(id)}
/>
</label>
</div>
))}
</form>
Related
The state of array values is not changing i have tried many times but still not succeeded is there a way that i missed somehow here is the attached code highlighting the problem. If anyone can help it would be much appreciated.
Class component handling form stepper
constructor(props) {
super(props);
this.state = {
step: 1,
propertyID:0,
responseMessage:"",
loading:false,
name:"",
address: "",
county:"",
city: "",
zipcode: "",
type: "",
specifictype: "",
formValues:[{beds:"",rent:"",numUnits:0,squarefeet:""}]
};
}
handleFormChange(i, e) {
let formValues = this.state.formValues;
console.log(formValues);
formValues[i][e.target.name] = e.target.value;
this.setState({ formValues });
}
render() {
const { step } = this.state;
const {
address,
name,
specifictype,
city,
county,
zipcode,
type,
formValues,
responseMessage
} = this.state;
const values = {
address,
name,
specifictype,
city,
zipcode,
type,
county,
formValues,
responseMessage
} ;
switch (step) {
case 3:
return(
<PropertyType
values={values}
add={this.addFormFields.bind(this)}
remove = {this.removeFormFields.bind(this)}
handleChange={this.handleFormChange}
prevStep={this.prevStep}
nextStep={this.getandSend}
/>
)
}
}
then here is the code of the component that handles the dynamic input fields.I had to reduce the code other parts are working fine do not worry about values,add,remove,prevStep and next step those are working just fine the problem is how i handle the change
function PropertyType({values,add,remove,handleChange,prevStep,nextStep}) {
return(
<>
<form action="">
{values.formValues.slice(0,5).map((element, index) => (
<div className="w-full md:w-9/12 flex mx-auto">
<div className="mb-6 mr-3">
<label
className="block mb-2 text-coolGray-800"
htmlFor=""
>
Beds
</label>
<select defaultValue={element.beds} onChange={e => handleChange(index, e)} className="block w-full p-3 leading-5 text-coolGray-900 border border-coolGray-200 rounded-lg shadow-md placeholder-coolGray-400 focus:outline-none focus:ring-2 focus:ring-color-main focus:ring-opacity-50 bg-white" aria-label="Default select example">
<option selected>Select bedrooms</option>
<option value="0">Studio</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4+">More than 4</option>
</select>
</div>
<div className="mb-2 mr-3">
<label
className="block mb-2 text-coolGray-800 font-medium"
htmlFor=""
>
Number of units
</label>
<input
defaultValue={element.numUnits}
onChange={e => handleChange(index, e)}
className="appearance-none block w-full p-3 leading-5 text-coolGray-900 border border-coolGray-200 rounded-lg shadow-md placeholder-coolGray-400 focus:outline-none focus:ring-2 focus:ring-color-main focus:ring-opacity-50"
type="number"
placeholder="10"
/>
</div>
<div className="mb-2 mr-3">
<label
className="appearance-none block mb-2 text-coolGray-800 font-medium"
htmlFor=""
>
Squarefeet
</label>
<input
defaultValue={element.squarefeet}
onChange={e => handleChange(index, e)}
className="appearance-none block w-full p-3 leading-5 text-coolGray-900 border border-coolGray-200 rounded-lg shadow-md placeholder-coolGray-400 focus:outline-none focus:ring-2 focus:ring-color-main focus:ring-opacity-50"
type="number"
placeholder="2000"
/>
</div>
<div className="mb-2 mr-3">
<label
className="block mb-2 text-coolGray-800 font-medium"
htmlFor=""
>
Rent
</label>
<input
defaultValue={element.rent}
onChange={e => handleChange(index, e)}
className="appearance-none block w-full p-3 leading-5 text-coolGray-900 border border-coolGray-200 rounded-lg shadow-md placeholder-coolGray-400 focus:outline-none focus:ring-2 focus:ring-color-main focus:ring-opacity-50"
type="number"
placeholder="30,000"
/>
</div>
{
index ?<div className="mb-2 mr-3 mt-8">
<button className=" inline-block py-3 px-7 mb-4 w-full text-base text-white font-medium text-center leading-6 bg-red-500/50 rounded-md shadow-sm
" onClick={remove}>Remove</button> </div>
: null
}
</div>
))}
</>
)
}
You need to update the reference of the formValues array with spread operator.
handleFormChange(i, e) {
let formValues = this.state.formValues;
console.log(formValues);
formValues[i][e.target.name] = e.target.value;
this.setState({ formValues: [...formValues ]});
}
you have to make a copy of reference and then update as below:
handleFormChange = (i, e) => {
const formValues = [...this.state.formValues];
const res = formValues.map((val,idx)=>{
if(idx == i){
return ({...val, [e.target.name]: e.target.value})
}
return val
})
this.setState({ ...this.state, formValues: res});
}
finally found the answer for anyone who might need it
class Apps extends React.Component {
constructor(props) {
super(props)
this.state = {
formValues: [{ name: "", email : "" }]
};
}
handleChange(i, e) {
let formValues = this.state.formValues;
formValues[i][e.target.name] = e.target.value;
this.setState({ formValues });
}
render() {
const {formValues} = this.state;
return (
<PropertyType values={formValues} handleChange={this.handleChange.bind(this)} />
);
}
}
Here is the propertytype component
{values.map((element, index) => (
<div className="form-inline" key={index}>
<label>Name</label>
<input type="text" name="name" value={element.name || ""} onChange={e => handleChange(index, e)} />
<label>Email</label>
<input type="text" name="email" value={element.email || ""} onChange={e => handleChange(index, e)} />
{
index ?
<button type="button" className="button remove" onClick={() => remove(index)}>Remove</button>
: null
}
</div>
))}
This is my signup page & I don't get any error with post request with thunderclient but error occurs when using Signup page. I am stuck at this from a long time and I am intermediate in JavaScript. This is my second NextJs program. The users can not sign in to this, if I remove password, user and name's required field it adds an empty entry to mongodb.
import React from "react";
import { useState } from "react";
import Link from "next/link";
const Signup = () => {
const [name, setName] = useState()
const [email, setEmail] = useState()
const [password, setPassword] = useState()
const handleChange = (e) => {
if(e.target.name == 'name'){
setName(e.target.value);
}
else if(e.target.name == 'email'){
setEmail(e.target.value);
}
else if(e.target.name == 'password'){
setPassword(e.target.value);
}
};
const handleSubmit = async (e) => {
e.preventDefault()
const data = { name, email, password }
let res = await fetch('http://localhost:3000/api/signup', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
});
let response = await res.json();
console.log(response);
setName('')
setEmail('')
setPassword('')
};
return (
<div className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 flex flex-col">
<form onSubmit={handleSubmit} className='mt-8 space-y-10' method="POST">
<div className="mb-4">
<label
className="block text-grey-darker text-sm font-bold mb-2"
htmlFor="name"
>
Name
</label>
<input
value={name}
onChange={handleChange}
required
className="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker"
id="name"
type="text"
placeholder="name"
/>
</div>
<div className="mb-4">
<label
className="block text-grey-darker text-sm font-bold mb-2"
htmlFor="email"
>
Email
</label>
<input
value={email}
onChange={handleChange}
required
className="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker"
id="email"
type="email"
placeholder="email"
/>
</div>
<div className="mb-6">
<label
className="block text-grey-darker text-sm font-bold mb-2"
htmlFor="password"
>
Password
</label>
<input
value={password}
onChange={handleChange}
required
className="shadow appearance-none border border-red rounded w-full py-2 px-3 text-grey-darker mb-3"
id="password"
type="password"
placeholder="Password"
/>
<p className="text-red text-xs italic">Please choose a password.</p>
</div>
<div className="flex items-center justify-between">
<button
className="bg-blue hover:bg-blue-dark text-black font-bold py-2 px-4 rounded"
type="submit"
>
Sign In
</button>
<a
className="inline-block align-baseline font-bold text-sm text-blue hover:text-blue-darker"
href={"/forgot"}
>
Forgot Password?
</a>
</div>
</form>
</div>
);
};
export default Signup;
This is my models file
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema(
{
name: {type: String, required: true},
email: {type: String, required: true, unique: true},
password: {type: String, required: true},
}, {timestamps: true}
);
mongoose.models = {}
// export default mongoose.models.User || mongoose.model("User", UserSchema);
export default mongoose.model("User", UserSchema);
This is my API
import connectDb from "../../middleware/mongoose"
import User from "../../models/User"
const handler = async (req, res)=> {
if(req.method == 'POST'){
let u = new User(req.body)
await u.save()
res.status(200).json({success: "success"})
}
else{
res.status(400).json({error: "this method is not allowed"})
}
}
export default connectDb(handler);
This is what I get when I log response
{
properties: [Object],
kind: 'required',
path: 'email',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
},
I have a function that gets called on a Form submit.
This function returns a paragraph tag depending on the callback from an Axios POST request.
How do I inject this paragraph tag into my page so that it would display in the DOM?
Im sure it is quite simple but I am just struggling with what would be the best approach to do this
FUNCTION:
axios({
method: "POST",
data: {
username: registerUsername,
email: registerEmail,
password: registerPassword,
},
withCredentials: true,
url: "http://localhost:4000/register",
})
.then((res) => {
if (res.data === "Username already exists") {
return (
<p className="text-sm text-red-600">Username already exists</p>
);
} else {
<p className="text-sm text-red-600">Account registered</p>;
}
})
.catch((err) => console.log(err));
};
FORM:
<form onSubmit={handleSubmit(onSubmitHandler)}>
<label className="font-semibold">Username</label>
<input
placeholder="Username"
name="username"
className="block border border-grey-light w-full p-3 rounded mb-4"
onChange={(e) => setRegisterUsername(e.target.value)}
{...register("username", {
required: "An username is required",
})}
></input>
<p className="text-sm text-red-600">
{errors?.username && errors.username.message}
</p>
<label className="font-semibold">Email</label>
<input
placeholder="E-mail"
name="email"
className="block border border-grey-light w-full p-3 rounded mb-4"
onChange={(e) => setRegisterEmail(e.target.value)}
{...register("email", {
required: "Please enter a valid e-mail",
})}
></input>
<p className="text-sm text-red-600">
{errors?.email && errors.email.message}
</p>
<label className="font-semibold">Password</label>
<input
placeholder="Password"
type="password"
name="password"
className="block border border-grey-light w-full p-3 rounded mb-4"
onChange={(e) => setRegisterPassword(e.target.value)}
{...register("password", {
required: "Password must be min 8 or max 24 characters",
min: 8,
max: 24,
})}
></input>
<p className="text-sm text-red-600">
{errors?.password && errors.password.message}
</p>
<label className="font-semibold">Confirm Password</label>
<input
placeholder="Confirm Password"
type="password"
name="confirmPassword"
id="password"
className="block border border-grey-light w-full p-3 rounded mb-4"
{...register("confirmPassword")}
onChange={(e) => setRegisterUsername(e.target.value)}
></input>
<p className="text-sm text-red-600">
{errors?.confirmPassword && errors.confirmPassword.message}
</p>
<button
// onClick={submitRegistration}
type="submit"
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full"
>
Create Account
</button>
</form>
useState will help in this
const [error,setError]=useState("")
FUNCTION:
axios({
method: "POST",
data: {
username: registerUsername,
email: registerEmail,
password: registerPassword,
},
withCredentials: true,
url: "http://localhost:4000/register",
})
.then((res) => {
if (res.data === "Username already exists") {
return (
setError("Username already exists")//Change here
);
} else {
setError("Account registered")//Change here
}
})
.catch((err) => console.log(err));
};
FORM:
<form onSubmit={handleSubmit(onSubmitHandler)}>
{error && <p className="text-sm text-red-600">{error}</p>}
</form>
I'm trying to save information in a table, which also has a field of type varbinary(max) (an image) (SQL Server)
class AddDoctor extends Component {
state = {
file: null,
name: "",
phoneNumber: "",
email: "",
status: "Active",
specialty: "",
specialities: [],
};
componentDidMount() {
const URL = "http://localhost:55317/api/TSpecialties";
ApiService.get(URL)
.then((data) => this.setState({ specialities: data }))
.catch((err) => console.log(err));
}
imgClick = () => {
const file = document.querySelector("#id-file");
file.click();
};
handleChange = (e) => {
const state = this.state;
state[e.target.name] = e.target.value;
this.setState({
...state,
});
};
handleFileChange = (event) => {
this.setState({
file: URL.createObjectURL(event.target.files[0]),
});
};
handleSubmit = (e) => {
e.preventDefault();
const URL = "http://localhost:55317/api/TDoctors/";
const DATA = {
doctorName: this.state.name,
doctorProfileImg: this.state.file,
doctorPhoneNumber: this.state.phoneNumber,
doctorEmail: this.state.email,
doctorStatus: this.state.status,
doctorSpecialtyId: Number(this.state.specialty),
};
let formData = new FormData();
formData.append("doctorProfileImg", DATA.doctorProfileImg);
formData.append("doctorName", DATA.doctorName);
formData.append("doctorEmail", DATA.doctorEmail);
formData.append("doctorPhoneNumber", DATA.doctorPhoneNumber);
formData.append("doctorStatus", DATA.doctorStatus);
formData.append("doctorSpecialtyId", DATA.doctorSpecialtyId);
const options = {
method: "POST",
body: formData
};
fetch(URL, options)
.then(res => console.log(res))
.catch(err => console.log("ERR: " + err))
};
render() {
return (
<div>
<form className="row g-3" onSubmit={this.handleSubmit}>
<div className="col-md-6">
<label htmlFor="name" className="form-label">
Name
</label>
<input
type="text"
className="form-control"
id="name"
name="name"
onChange={this.handleChange}
placeholder="Input your name"
/>
</div>
<div className="col-md-6">
<label htmlFor="email" className="form-label">
Email
</label>
<input
type="text"
onChange={this.handleChange}
name="email"
className="form-control"
id="email"
/>
</div>
<div className="col-md-6">
<label className="mb-2" htmlFor="phoneNumber">
Phone Number
</label>
<div className="input-group mb-2 mr-sm-2">
<div className="input-group-prepend">
<div className="input-group-text">+51</div>
</div>
<input
type="text"
onChange={this.handleChange}
className="form-control"
id="phoneNumber"
name="phoneNumber"
placeholder="Phone Number"
/>
</div>
</div>
<div className="col-md-12">
<label htmlFor="specialty" className="form-label">
Specialty
</label>
{/* */}
<select
id="specialty"
name="specialty"
onChange={this.handleChange}
className="form-select"
>
<option defaultValue>Choose...</option>
{this.state.specialities.map((sp) => (
<option value={sp.specialtyId}>
{sp.specialtyName}
</option>
))}
</select>
{/* */}
</div>
<div className="col-12 my-5">
<button
type="submit"
className="btn btn-outline-success w-100"
>
Save
</button>
</div>
</form>
<div className="col mx-5" style={{ minWidth: "250px" }}>
<img
src={ this.state.file}
id="img-select"
onClick={this.imgClick}
className="img-fluid img-thumbnail"
alt="doctor-img"
/>
<input
type="file"
style={{ display: "none" }}
onChange={this.handleFileChange}
id="id-file"
/>
</div>
</div>
);
}
}
Controller POST:
// POST: api/TDoctors
[HttpPost]
public async Task<IActionResult> PostTDoctor([FromBody] TDoctor tDoctor)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.TDoctor.Add(tDoctor);
await _context.SaveChangesAsync();
return CreatedAtAction("GetTDoctor", new { id = tDoctor.DoctorId }, tDoctor);
}
response on console developer tools when submit form:
and...
I have searched a lot of information and I cannot find the solution. I tried placing the multipart/form-data and it doesn't work either. I hope you can help me please.
Saving binary data to a SQL table is not a good practice, please use Azure Blob storage or some other storage service to store the files and just save the path of the file in the database column of a table
I have a react component where I submit a form using formik
import { Field, Form, FormikProps, Formik } from "formik";
import {
Combobox,
ComboboxInput,
ComboboxOptionText,
ComboboxPopover,
ComboboxOption,
ComboboxList,
} from "#reach/combobox";
import {
createShop,
getMerchants,
getActiveMerchants,
} from "../../../request/shop";
import { useState } from "react";
import { useQuery } from "react-query";
import "styled-components/macro";
import Loader from "react-spinners/BarLoader";
import { useDebounce } from "use-debounce";
import { toast } from "react-toastify";
import { UploadImage } from "../../../common/UploadImage";
import { removeaSinglItem } from "../../../utils/helper";
import { KeyPerson } from "../component/KeyPerson";
import { CategoryHead } from "../component/CategoryHead";
import { BDM } from "../component/BDM";
import { KAM } from "../component/KAM";
import { VM } from "../component/VM";
import ImageUploadCrop from "../../../common/ImageUploadCrop";
import MapViewWithSearch from "../../../common/MapViewWithSearch";
import { Button } from "../../../common/Button";
export function CreateShop(): JSX.Element {
const [searchMerchantText, setSearchMerchantText] = useState<string>("");
const [selectedMerchant, setSelectedMerchant] = useState<{
merchant_name: string;
merchant_code: string;
}>({ merchant_name: "", merchant_code: "" });
const [throttledMerchantText] = useDebounce(searchMerchantText, 500);
const queryMerchantSearch = useQuery(
["merchant-search", throttledMerchantText],
() => getActiveMerchants(`name=${searchMerchantText}&limit=10&page=1`),
{
enabled: Boolean(throttledMerchantText),
}
);
const [searchMotherShopSlug, setSearchMotherShopSlug] = useState<string>("");
const [selectedSlug, setSelectedSlug] = useState<{
slug: string;
}>({ slug: "" });
const [throttledSlug] = useDebounce(searchMotherShopSlug, 500);
const querySlug = useQuery(
["slug-search", throttledSlug],
() =>
getMerchants(
selectedMerchant.merchant_code,
`slug=${searchMotherShopSlug}&limit=10&page=1`
),
{
enabled: Boolean(throttledSlug),
}
);
const merchantDetails = querySlug?.data?.data?.data?.shops ?? [];
const merchants = queryMerchantSearch?.data?.data?.data?.merchants ?? [];
return (
<div className="min-h-screen py-5 p-4">
<h1 className="mb-5">Create Shop</h1>
<Formik
initialValues={{
name: "",
logo_image: "",
image: "",
longitude: "",
latitude: "",
contact_number: "",
mother_shop_slug: "",
shop_type: "regular",
bin_no: "",
trade_license_no: "",
key_personnel: [
{
name: "",
designation: "",
phone_no: "",
email: "",
},
],
category_head: [
{
username: "",
},
],
}}
onSubmit={async (values, actions) => {
try {
actions.setSubmitting(true);
const reqbody: any = {
name: values.name,
longitude: values.longitude,
latitude: values.latitude,
logo_image: values.logo_image,
image: values.image,
contact_number: values.contact_number,
mother_shop_slug: selectedSlug.slug,
shop_type: values.shop_type,
bin_no: values.bin_no,
trade_license_no: values.trade_license_no,
key_personnel: values.key_personnel,
category_head: values.category_head,
};
const res = await createShop(reqbody);
if (res.status == 201) {
toast.success(res.data.message);
actions.setSubmitting(false);
await removeaSinglItem("createShop");
window.location.reload();
} else {
toast.error(res.data.message);
}
} catch (err) {
console.log(err);
actions.setSubmitting(false);
toast.error("Failed to create Shop");
}
}}
validate={(values) => {
const errors: any = {};
if (!values.name) {
errors.name = "Name is Required";
}
if (!values.address) {
errors.address = "Address is Required";
}
if (!values.latitude) {
errors.latitude = "Latitude is Required";
}
if (!values.longitude) {
errors.longitude = "Longitude is Required";
}
return errors;
}}
>
{(props: FormikProps<any>) => {
return (
<Form>
<fieldset className="border mb-2 p-4">
<legend className="px-2 ml-2 font-semibold">Shop:</legend>
<div className="flex items-center">
<div className="mb-6">
<ImageUploadCrop
title="Upload Logo"
setFieldValue={(value: string) =>
props.setFieldValue("logo_image", value)
}
logo={props.values.logo_image}
/>
</div>
<div className="ml-6 mb-6">
<ImageUploadCrop
title="Upload Cover Image"
setFieldValue={(value: string) =>
props.setFieldValue("image", value)
}
logo={props.values.image}
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4 w-full">
<div className="mb-6">
<label htmlFor={"name"}>{"Name*"}</label>
<Field
type="text"
name="name"
placeholder="Name"
id={"name"}
className={"form-input"}
/>
{props.errors.name && (
<p className="text-red-500">{props.errors.name}</p>
)}
</div>
</div>
<div className="grid grid-cols-2 gap-4 w-full">
<div className="mb-6">
<label htmlFor={"latitude"}>{"Latitude*"}</label>
<Field
type="number"
name="latitude"
id="latitude"
className={"form-input"}
/>
{props.errors.latitude && (
<p className="text-red-500">{props.errors.latitude}</p>
)}
</div>
<div className="mb-6">
<label htmlFor={"longitude"}>{"Longitude*"}</label>
<Field
type="number"
name="longitude"
id="longitude"
className={"form-input"}
/>
{props.errors.longitude && (
<p className="text-red-500">{props.errors.longitude}</p>
)}
</div>
</div>
<div className="mb-6">
<MapViewWithSearch
lat={
props.values.latitude ? props.values.latitude : 23.777176
}
address={props.values.address}
lng={
props.values.longitude
? props.values.longitude
: 90.399452
}
onChangeAddress={(lat, lng, address) => {
props.setFieldValue("address", address);
props.setFieldValue("latitude", lat);
props.setFieldValue("longitude", lng);
}}
/>
</div>
<div className="grid grid-cols-2 gap-4 w-full">
<div className="mb-6">
<label htmlFor={"contact_number"}>{"Contact Number"}</label>
<Field
type="number"
name="contact_number"
id="contact_number"
className={"form-input"}
/>
</div>
<div className="mb-6">
<label htmlFor={"shop_type"}>{"Shop Type"}</label>
<Field as="select" name="shop_type" className="form-select">
<option value="regular">Regular</option>
<option value="campaign">Campaign</option>
<option value="express">Express</option>
</Field>
</div>
<div className="mb-6">
<label htmlFor={"organisation_type"}>
{"Organization Type"}
</label>
<Field
as="select"
name="organisation_type"
className="form-select"
>
<option value="small">Small</option>
<option value="medium">Medium</option>
<option value="large">Large</option>
</Field>
</div>
<div className="grid grid-cols-2 gap-4 w-full">
<div className="mb-4" role="group">
<p className="block mb-2">Is Delivery Hero Allowed</p>
<label className="mr-4">
<input
name="is_delivery_hero_allowed"
type="radio"
checked={!props.values.is_delivery_hero_allowed}
onChange={() => {
props.setFieldValue(
"is_delivery_hero_allowed",
false
);
}}
/>{" "}
<span className="ml-2">No</span>
</label>
<label>
<input
name="is_delivery_hero_allowed"
type="radio"
checked={props.values.is_delivery_hero_allowed}
onChange={() =>
props.setFieldValue(
"is_delivery_hero_allowed",
true
)
}
/>{" "}
<span className="ml-2">Yes</span>
</label>
</div>
<div className="mb-4" role="group">
<p className="block mb-2">Is Cash On Delivery Allowed</p>
<label className="mr-4">
<input
name="is_cod_allowed"
type="radio"
checked={!props.values.is_cod_allowed}
onChange={() => {
props.setFieldValue("is_cod_allowed", false);
}}
/>{" "}
<span className="ml-2">No</span>
</label>
<label>
<input
name="is_cod_allowed"
type="radio"
checked={props.values.is_cod_allowed}
onChange={() =>
props.setFieldValue("is_cod_allowed", true)
}
/>{" "}
<span className="ml-2">Yes</span>
</label>
</div>
</div>
</div>
</fieldset>
<fieldset className="border mb-2 p-4">
<legend className="px-2 ml-2 font-semibold">
Mother Shop:
</legend>
<div className="mb-4" role="group">
<p className="block mb-2">Is Mother Shop</p>
<label className="mr-4">
<input
name="is_mother_shop"
type="radio"
checked={!props.values.is_mother_shop}
onChange={() => {
props.setFieldValue("is_mother_shop", false);
}}
/>{" "}
<span className="ml-2">No</span>
</label>
<label>
<input
name="is_mother_shop"
type="radio"
checked={props.values.is_mother_shop}
onChange={() =>
props.setFieldValue("is_mother_shop", true)
}
/>{" "}
<span className="ml-2">Yes</span>
</label>
</div>
{!props.values.is_mother_shop && (
<div>
<Combobox>
<label className="relative block mb-2">
<p>Mother Shop Slug</p>
<ComboboxInput
placeholder="Search Mother Shop Slug ..."
className="form-input"
onChange={(e: any) =>
setSearchMotherShopSlug(e.target.value)
}
/>
</label>
{Array.isArray(merchantDetails) && (
<ComboboxPopover
portal={false}
className="absolute bg-white border w-auto"
css={`
z-index: 2001;
`}
>
{queryMerchantSearch.isLoading ? (
<div className="flex items-center justify-center p-4">
<Loader />
</div>
) : merchantDetails.length > 0 ? (
<ComboboxList className="bg-white shadow-md ">
{merchantDetails.map(
(motherSlug, idx: number) => {
return (
<div
key={idx}
className="p-2 hover:bg-gray-100"
>
<div className="flex items-center">
<ComboboxOption
value={motherSlug.slug}
className="w-full text-xs cursor-pointer"
onClick={() => {
setSelectedSlug({
slug: motherSlug.slug,
});
}}
>
<ComboboxOptionText /> -{" "}
<span className="capitalize font-semibold">
{motherSlug.slug}
</span>
</ComboboxOption>
</div>
</div>
);
}
)}
</ComboboxList>
) : (
<div className="flex items-center justify-center p-8">
{throttledSlug
? "No results found"
: "Type Mother Shop slug ..."}
</div>
)}
</ComboboxPopover>
)}
</Combobox>
</div>
)}
{props.values.is_mother_shop && (
<div className="mb-6">
<>
<div className="grid grid-cols-2 gap-4 w-full">
<div className="mb-6">
<label htmlFor={"bin_no"}>{"BIN No"}</label>
<Field
type="number"
name="bin_no"
id="bin_no"
className={"form-input"}
/>
</div>
<div className="mb-6">
<label htmlFor={"trade_license_no"}>
{"Trade License No"}
</label>
<Field
type="text"
name="trade_license_no"
id="trade_license_no"
className={"form-input"}
/>
</div>
</div>
<div className="block mb-6">
<p className="mb-2">
Key Personnel
<button
type="button"
onClick={() =>
props.setFieldValue("key_personnel", [
...props.values.key_personnel,
{
name: "",
designation: "",
phone_no: "",
email: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add Key Personnel
</button>
</p>
{props.values.key_personnel.map(
(
kp: {
name: string;
designation: string;
phone_no: string;
email: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<KeyPerson
setFieldValue={props.setFieldValue}
kps={props.values.key_personnel}
index={index}
kp={kp}
/>
</div>
)
)}
</div>
<div className="block mb-6">
<p className="mb-2">
Category Head
<button
type="button"
onClick={() =>
props.setFieldValue("category_head", [
...props.values.category_head,
{
username: "",
},
])
}
className="float-right ml-4 text-sm underline"
>
Add Category Head
</button>
</p>
{props.values.category_head.map(
(
ch: {
username: string;
},
index: number
) => (
<div
key={index}
className="flex items-center p-4 mt-2 bg-gray-100 rounded"
>
<CategoryHead
setFieldValue={props.setFieldValue}
chs={props.values.category_head}
index={index}
ch={ch}
/>
</div>
)
)}
</div>
</div>
</>
</div>
)}
</fieldset>
<Button black type="submit">
Submit
</Button>
</Form>
);
}}
</Formik>
</div>
);
}
in the current implementation I submit all the values of the form be it empty or not, but now my new API requires me to submit only the non empty fields in the form during form submit. How can I do it in this code implementation or is there any method or way provided by Formik to achieve this.
function nonEmptyObject(obj: any) {
for (const propName in obj) {
if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ""
) {
delete obj[propName];
}
}
return obj;
}
if (values.key_personnel) {
reqbody.key_personnel = values.key_personnel;
}
if (values.category_head) {
reqbody.category_head = values.category_head;
}
if (values.bdm) {
reqbody.bdm = values.bdm;
}
if (values.kam) {
reqbody.bdm = values.kam;
}
if (values.vm) {
reqbody.vm = values.vm;
}
const finalPayload = nonEmptyObject(reqbody);
const res = await createShop(finalPayload);
console.log({ finalPayload });
console.log({ res });