Forest1206
Forest1206

Reputation: 73

How to validate React-quill with React-hook-form and yup?

I used

Normal inputs and textareas working as expected, but validation for react-quill is not working.

These are my code snippets.

Custom react-quill wrapper element

import React, { useRef, useState } from "react";
import PropTypes from "prop-types";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";
import "react-quill/dist/quill.bubble.css";
import "react-quill/dist/quill.core.css";

function Editor(props) {
  const [theme, setTheme] = useState("snow");
  const { id, value, inputRef, placeholder, onChange } = props;

  return (
    <ReactQuill
      id={id}
      ref={inputRef}
      theme={theme}
      onChange={onChange}
      value={value}
      modules={{
        toolbar: {
          ...Editor.modules.toolbar,
          handlers: {
            //   image: handleImageUpload,
          },
        },
        ...Editor.modules,
      }}
      formats={Editor.formats}
      bounds={".app"}
      placeholder={placeholder ?? ""}
    />
  );
}

/*
 * Quill modules to attach to editor
 * See https://quilljs.com/docs/modules/ for complete options
 */
Editor.modules = {
  toolbar: [
    // [{ header: '1' }, { header: '2' }, { font: [] }],
    // [{ size: [] }],
    [{ size: ["small", false, "large", "huge"] }], // custom dropdown
    [{ header: [1, 2, 3, 4, 5, 6, false] }],
    ["bold", "italic", "underline", "strike", "blockquote"],
    [
      { list: "ordered" },
      { list: "bullet" },
      { indent: "-1" },
      { indent: "+1" },
    ],
    ["link", "image", "video"],
    ["clean"],
    [{ color: [] }, { background: [] }], // dropdown with defaults from theme
    [{ font: [] }],
    [{ align: [] }],
  ],
  clipboard: {
    // toggle to add extra line breaks when pasting HTML:
    matchVisual: false,
  },
};
/*
 * Quill editor formats
 * See https://quilljs.com/docs/formats/
 */
Editor.formats = [
  "header",
  "font",
  "size",
  "bold",
  "italic",
  "underline",
  "strike",
  "blockquote",
  "list",
  "bullet",
  "indent",
  "link",
  "image",
  "video",
];

/*
 * PropType validation
 */
Editor.propTypes = {
  placeholder: PropTypes.string,
};

export default Editor;

This is form component

const validationSchema = Yup.object().shape({
    companyName: Yup.string().required("Company Name is required"),
    ... ...

    jobDescription: Yup.string().required("Job description is required"), // react-quill

    ... ...
    howtoApply: Yup.string().required("This field is required"),
    applyUrl: Yup.string().required("This field is required"),
    applyEmail: Yup.string().required("This field is required"),

  });

const formOptions = { resolver: yupResolver(validationSchema) };

const { register, handleSubmit, reset, control, formState } = useForm(
    formOptions
  );

  useEffect(() => {
    console.log("formState", formState); // log for form value changes
  });


    ... ... ...

<Controller
                control={control}
                name="jobDescription"
                // rules={{
                //   required: "Description must have some content.",
                //   validate: (value) => {
                //     console.log("Controller", value);
                //     return (
                //       value.split(" ").length > 10 ||
                //       "Enter at least 10 words in the body."
                //     );
                //   },
                // }}
                render={({
                  field: { onChange, onBlur, value, name, ref },
                  fieldState: { invalid, isTouched, isDirty, error },
                  formState,
                }) => (
                  <Editor
                    onChange={(description, delta, source, editor) => {
                      console.log(
                        "onChange:description",
                        description,
                      );
                      console.log("inputRef", ref);
                      onChange(description);
                    }}
                    value={value || ""}
                    inputRef={ref}
                    theme="snow"
                    id="jobDescription"
                  />
                )}
              />

I checked these issues, https://github.com/zenoamaro/react-quill/issues/635

https://github.com/react-hook-form/react-hook-form/discussions/3372

but still not working.

Current behavior

I confirmed the changed markdown logged in console (onChange function in Editor), but can't see formState log of useEffect hook upon editor change. (regardless of add rules prop to Controller or not)

Any help would be much appreciated

Thank you

Upvotes: 4

Views: 12194

Answers (3)

LongDev
LongDev

Reputation: 221

you can try with "react-hook-form"

  <FormField
            control={form.control}
            name="content"
            render={({ field }) => (
              <FormItem>
                <FormLabel className="text-white">Picture</FormLabel>
                <FormControl>
                  <ReactQuill
                    {...field}
                    ref={quillRef}
                    modules={modules}
                    theme="snow"
                    placeholder={"Write Description"}
                    className="mt-4 text-white"
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />




export const PostSchema: z.ZodType<PostType> = z.object({
  id: z.number(),
  shortDesc: z.string().min(4, "Minumun 4 in legnth"),
});

Upvotes: 0

Ashadul Mridha
Ashadul Mridha

Reputation: 135

<Controller
  name="desc"
  control={control}
  rules={{
    required: "Please enter task description",
  }}
  theme="snow"
  modules={modules}
  render={({ field }) => (
    <ReactQuill
      {...field}
      placeholder={"Write Description"}
      onChange={(text) => {
        field.onChange(text);
      }}
    />
  )}
/>;

You Can Add Validator As ur like

Upvotes: 3

Aditya Duvvuri
Aditya Duvvuri

Reputation: 91

export default function App() {
  const {
    register,
    handleSubmit,
    setValue,
    watch,
    formState: { errors }
  } = useForm();

  useEffect(() => {
    register("emailContent", { required: true, minLength: 15 });
  }, [register]);

  const onEditorStateChange = (editorState) => {
    setValue("emailContent", editorState);
  };

  const onSubmit = (data) => {
    console.log(data);
  };

  const editorContent = watch("emailContent");

  return (
    <div className="App">
      <ReactQuill
        theme="snow"
        value={editorContent}
        onChange={onEditorStateChange}
      />
      <p className="Error">{errors.emailContent && "Enter valid content"}</p>
      <input type="submit" onClick={handleSubmit(onSubmit)} />
    </div>
  );
}

I have created a code sandbox with a working example for react-hook-form. Here is the link:

https://codesandbox.io/s/quill-with-react-hook-form-validation-cdjru

Upvotes: 8

Related Questions