Dinis Zabrodsky
Dinis Zabrodsky

Reputation: 11

How to create a gallery with react-quilljs

I’m using react-quilljs to add posts to my blog, and now I need to implement a gallery feature using this library. I want to create a gallery in the format

<ul><li><img></li></ul>.  

I’ve searched online and checked various resources, but I couldn’t figure out exactly how to implement this functionality. Has anyone already done something similar? I’d really appreciate any advice, examples, or guidance on how to make this work. npm lib - https://www.npmjs.com/package/react-quilljs

import Quill from 'quill';

const BlockEmbed = Quill.import('blots/block/embed');

class GalleryBlot extends BlockEmbed {
    static create(value) {
        
        const node = super.create();

        if (value && value.images) {
            const galleryContainer = document.createElement('div');
            galleryContainer.classList.add('quill-gallery');

            value.images.forEach((url) => {
                const img = document.createElement('img');
                img.setAttribute('src', url);
                img.setAttribute('alt', 'Gallery Image');
                galleryContainer.appendChild(img);
            });

            node.appendChild(galleryContainer);
        }

        return node;
    }

    static value(node) {
        const images = [];
        node.querySelectorAll('img').forEach((img) => {
            images.push(img.getAttribute('src'));
        });
        console.log('GalleryBlot.value повертає:', images);
        return { images };
    }
}

GalleryBlot.blotName = 'gallery';
GalleryBlot.tagName = 'div';
GalleryBlot.className = 'quill-gallery';

Quill.register(GalleryBlot, true);

console.log(Quill.imports);

export default GalleryBlot;

part of the component code

'use client';

import { useQuill } from 'react-quilljs';

import { useEffect } from 'react';

import './module/GalleryBlot';

import 'quill/dist/quill.snow.css';
import './QuillJS.scss';
import styles from './QuillJS.module.scss';

const QuillJS = ({ quillValue, setQuillValue, curentLang }) => {
  const { quill, quillRef, Quill } = useQuill();

  useEffect(() => {
    if (!quill) return;

    quill.on('text-change', handleTextChange);
    quill.getModule('toolbar').addHandler('image', selectLocalImage);

    return () => {
      quill.off('text-change', handleTextChange);
    };
  }, [quill, curentLang]);

  useEffect(() => {
    if (!quill) return;
    quill.root.innerHTML = quillValue[curentLang] || '';
  }, [quill, curentLang]);

  const handleTextChange = () => {
    setQuillValue((prev) => ({
      ...prev,
      [curentLang]: quill.root.innerHTML,
    }));
  };

  const selectLocalImage = () => {
    const input = document.createElement('input');
    input.setAttribute('type', 'file');
    input.setAttribute('accept', 'image/*');
    input.setAttribute('multiple', 'true');
    input.click();

    input.onchange = () => {
      const files = Array.from(input.files);

      if (files.length > 0) {
        saveToServer(files);
      }
    };
  };

  const saveToServer = async (files) => {
    const body = new FormData();
    files.forEach((file, index) => body.append(`files-${index}`, file));

    try {
      const res = await fetch('/api/postImage', {
        method: 'POST',
        body,
      });

      const data = await res?.json();

      if (res.ok && data.urls) {
        if (files.length === 1) {
          insertToEditor(data.urls[0]);
        } else {
          insertGalleryToEditor(data.urls);
        }
      } else {
        console.error('Помилка завантаження зображення:', data.message);
      }
    } catch (error) {
      console.error('Помилка завантаження зображення:', error);
    }
  };

  const insertToEditor = (url) => {
    const range = quill.getSelection();
    quill.insertEmbed(range.index, 'image', url);
  };

   const insertGalleryToEditor = (urls) => {
     const range = quill.getSelection();
     quill.insertEmbed(range.index, 'gallery', urls);
   };

  return (
    <li className={styles.QuillJS}>
      <div ref={quillRef} />
    </li>
  );
};

export default QuillJS;

Upvotes: 0

Views: 32

Answers (0)

Related Questions