繁体   English   中英

在formik表单中仅发送非空值在react js中提交

[英]Send only non empty values in formik form submit in react js

我有一个反应组件,我在其中使用 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>
  );
}

在当前实现中,无论是否为空,我都会提交表单的所有值,但现在我的新 API 要求我在表单提交期间仅提交表单中的非空字段。 我该如何在这个代码实现中做到这一点,或者 Formik 是否提供了任何方法或方式来实现这一点。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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