sickdyd / react-search-autocomplete

A search box that filters the provided array of objects
https://sickdyd.github.io/react-search-autocomplete
MIT License
222 stars 85 forks source link

How to use ReactSearchAutocomplete with formik and yup #83

Open varsha-M-I opened 2 years ago

varsha-M-I commented 2 years ago

I want to use ReactSearchAutocomplete with formik and yup how to validate with yup and how to render the component as children of form field.

Package.json

{
  "name": "react",
  "version": "1.0.0",
  "description": "React example starter project",
  "keywords": [
    "react",
    "starter"
  ],
  "main": "src/index.js",
  "dependencies": {
    "bootstrap": "5.2.0",
    "formik": "2.2.9",
    "react": "17.0.0",
    "react-bootstrap": "2.5.0",
    "react-dom": "17.0.0",
    "react-scripts": "4.0.0",
    "react-search-autocomplete": "7.2.2",
    "yup": "0.32.11"
  },
  "devDependencies": {
    "@babel/runtime": "7.13.8",
    "typescript": "4.1.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

Codesandbox example (https://codesandbox.io/s/amazing-diffie-o4hbod)

Visit this codesandbox example for reference https://codesandbox.io/s/amazing-diffie-o4hbod

To Reproduce

import React, { useState } from "react";
import { Container, Form, Row } from "react-bootstrap";
import { Formik, Field } from "formik";
import * as Yup from "yup";
import { Button } from "react-bootstrap";
import SearchComponent from "./SearchComponent";

const FormComponent = () => {
  const [searchString, setSearchString] = useState("");

  const schema = Yup.object().shape({
    comment: Yup.string().required("Comment is required"),
    assignment: Yup.array()
      .min(1, "At least one option is required")
      .required()
      .nullable()
  });

  return (
    <Container className="my-3">
      <Row>
        <Formik
          validationSchema={schema}
          onSubmit={(values) => {
            console.log(values);
          }}
          initialValues={{
            comment: "",
            assignment: {}
          }}
        >
          {({
            handleSubmit,
            handleChange,
            handleBlur,
            values,
            touched,
            isValid,
            errors
          }) => (
            <Form noValidate onSubmit={handleSubmit}>
              <Form.Group
                controlId="validationFormik03"
                className="position-relative mb-3"
              >
                <Form.Control
                  as="textarea"
                  rows={3}
                  placeholder={"Comment"}
                  name="comment"
                  value={values.comment}
                  onChange={handleChange}
                  isInvalid={touched.comment && errors.comment}
                />

                <Form.Control.Feedback type="invalid" className="text-danger">
                  {errors.comment}
                </Form.Control.Feedback>
              </Form.Group>
              <Form.Group>
                {/* <Form.Control
                  // as="select"
                  name="assignment"
                  component={
                    <SearchComponent
                      searchString={searchString}
                      setSearchString={setSearchString}
                    />
                  }
                  isInvalid={touched.assignment && errors.assignment}
                /> */}
                {
                  <SearchComponent>
                    <Field
                      placeholder={"Comment"}
                      name="assignment"
                      value={values.assignment}
                      onChange={handleChange}
                      isInvalid={touched.assignment && errors.assignment}
                    />
                  </SearchComponent>
                }
                <Form.Control.Feedback type="invalid" className="text-danger">
                  {errors.assignment}
                </Form.Control.Feedback>
              </Form.Group>
              <div className=" float-right mt-3">
                <Button variant="primary" type="submit">
                  Submit
                </Button>
              </div>
            </Form>
          )}
        </Formik>
      </Row>
    </Container>
  );
};

export default FormComponent;

SearchComponent.js

import React from "react";
import { ReactSearchAutocomplete } from "react-search-autocomplete";
const SearchComponent = ({
  // field, // { name, value, onChange, onBlur }
  // form: { touched, errors }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
  ...props
}) => {
  const { searchString, setSearchString, children } = props;
  const items = [
    {
      id: 0,
      name: "Cobol"
    },
    {
      id: 1,
      name: "JavaScript"
    },
    {
      id: 2,
      name: "Basic"
    },
    {
      id: 3,
      name: "PHP"
    },
    {
      id: 4,
      name: "Java"
    }
  ];
  const handleOnSearch = (string, results) => {
    console.log(string, results);
  };
  const handleOnClear = () => {
    setSearchString("");
  };
  const handleOnSelect = (item) => {
    console.log(item);
  };
  return (
    <>
      <ReactSearchAutocomplete
        items={items}
        onSearch={handleOnSearch}
        onClear={handleOnClear}
        onSelect={handleOnSelect}
        inputSearchString={searchString}
        autoFocus
      >
        {children}
      </ReactSearchAutocomplete>
    </>
  );
};
export default SearchComponent;

Expected behavior Both comment and search fields should be validated with yup if we click on submit without selecting any options then error message should be shown same as comment field. If we enter comment and select one option and then if we click on submit we should get values object on formik onsubmit.

Screenshots

Screenshot 2022-08-10 163129

Additional context Add any other context about the problem here.