简体   繁体   中英

Send only non empty values in formik form submit in react js

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 });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM