zenoamaro / react-quill

A Quill component for React.
https://zenoamaro.github.io/react-quill
MIT License
6.59k stars 906 forks source link

React Quill Custom image handler #987

Open Kartik0899 opened 1 week ago

Kartik0899 commented 1 week ago

I am working with react-quill and my image handler is not working below is my code --

The error I'm getting is TypeError: quillRef.current.getEditor is not a function

import dynamic from "next/dynamic";
import "react-quill/dist/quill.snow.css";

const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });

const handleEditorImageUpload = async () => {
    const input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("accept", "image/*");
    input.click();
    input.onchange = async () => {
      const file = input.files[0];
      const uploadedImage = await uploadImage(file);
      if (uploadedImage) {
        let quill = quillRef.current.getEditor();
        const range = quill.getSelection();
        quill.insertEmbed(range.index, "image", uploadedImage.url);
      }
    };
  };

  let toolbarOptions = [
    [{ header: [1, 2, 3, 4, 5, 6] }, { font: [] }],
    [{ list: "ordered" }, { list: "bullet" }],
    ["bold", "italic", "underline", "strike"],
    ["image"],
  ];

  const modules = useMemo(
    () => ({
      toolbar: {
        container: toolbarOptions,
        handlers: { image: handleEditorImageUpload },
      },
    }),
    []
  );

  <ReactQuill
                ref={quillRef}
                value={body}
                onChange={setBody}
                modules={modules}
                placeholder="Write your blog content here..."
              />

It is giving me an error of getEditor

Error - TypeError: quillRef.current.getEditor is not a function

Any help would be much appreciated!

tjiptostevens commented 1 week ago

have you declared the quillRef..?

this code below work fine with me.

import  { useMemo, useRef } from "react";

. . .

const quillRef = useRef(null);

  const handleImageInserted = async (file) => {
    try {
      const compressedImage = await compressImage(file); // compress the image
      const imageUrl = await handleFsImageUpload(path, compressedImage); // upload to server
      const quill = quillRef.current.getEditor();
      const range = quill.getSelection();
      quill.insertEmbed(range.index, "image", imageUrl); // add an img tag to quill
    } catch (error) {
      console.error("Error handling image insertion:", error);
    }
  };
  const openImageFileDialog = () => {
    const input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("accept", "image/*");
    input.onchange = (event) => {
      const file = event.target.files[0];
      if (file) {
        handleImageInserted(file);
      }
    };
    input.click();
  };

  . . .
Kartik0899 commented 6 days ago

Hey @tjiptostevens, I tried using the code you provided but I am still getting the same error -

Error - Error handling image insertion: TypeError: quillRef.current.getEditor is not a function at handleImageInserted

Below is the dependencies - "react": "^18", "react-dom": "^18", "react-quill": "^2.0.0",

tjiptostevens commented 3 days ago

hhmm... how about this code. this work for me

import { useMemo, useRef, useState } from "react";
import dynamic from "next/dynamic";
import "react-quill/dist/quill.snow.css";

const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });

const TextEditor = ({ path = "/" }) => {
  const [body, setBody] = useState("");
  const quillRef = useRef(null);

  const handleImageInserted = async (file) => {
    try {
      const imageUrl = await handleFsImageUpload(path, file);  // image upload function
      const quill = quillRef.current.getEditor();
      const range = quill.getSelection();
      quill.insertEmbed(range.index, "image", imageUrl);
    } catch (error) {
      console.error("Error handling image insertion:", error);
    }
  };

  const openImageFileDialog = () => {
    const input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("accept", "image/*");
    input.onchange = (event) => {
      const file = event.target.files[0];
      if (file) {
        handleImageInserted(file);
      }
    };
    input.click();
  };

  const handleChange = (value) => {
    setBody(value);
  };

  const quillModules = useMemo(
    () => ({
      toolbar: {
        container: [
          ["bold", "italic", "underline", "strike"],
          [{ header: "1" }, { header: "2" }],
          [{ list: "ordered" }, { list: "bullet" }],
          ["link", "image", "youtube"], 
        ],
        handlers: {
          image: openImageFileDialog,
        },
      },
    }),
    []
  );

  return (
    <div className="form-group __texteditor">
      <label htmlFor="category">
        Content <b>*</b>
      </label>
      <ReactQuill
        ref={quillRef}
        value={body}
        onChange={handleChange}
        theme="snow"
        modules={quillModules}
      />
    </div>
  );
};

export default TextEditor;