We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to insert html into Quill React Component.
React version: "18.2.0" react-quill: "2.0.0" next:"14.1.0"
'use client'; import { useLazyQuery } from '@apollo/client'; import dynamic from 'next/dynamic'; import React, { useRef, useEffect, useState } from 'react'; import { getUserFullName, toastAlert } from '@/utils'; import 'react-quill/dist/quill.snow.css'; import { GET_ORGANIZATION_USERS } from '@/components/user-and-roles/graphql/queries/getOrganizationUsers.gql'; import { useSelector } from 'react-redux'; import { size } from 'lodash'; import { useDebounce } from '@/helpers/hooks'; const loadReactQuill = async () => { const { default: RQ } = await import('react-quill'); const reactQuillWithRef = ({ forwardedRef, ...props }) => <RQ ref={forwardedRef} {...props} />; return reactQuillWithRef; }; const ReactQuill = dynamic(loadReactQuill, { ssr: false }); const AppEditor = ({ readOnly = false, onChange, allowMention = false, value = '', placeholder = '', toolbarBottom = false, setMentionedIds = [] }) => { const editorRef = useRef(null); const quillContainerRef = useRef(null); const [showMentionList, setShowMentionList] = useState(false); const [mentionListPosition, setMentionListPosition] = useState({ top: 0, left: 0 }); const [cursorIndex, setCursorIndex] = useState({}); const userData = useSelector((state) => state.auth.user); const [agentsState, setAgentsState] = useState({ data: [], metaData: {}, loading: true, loaded: false, searchKeyword: '', optionData: { limit: 50, offset: 0, order: [['created_at', 'desc']] } }); const [getAgents] = useLazyQuery(GET_ORGANIZATION_USERS, { errorPolicy: 'all', fetchPolicy: 'no-cache', variables: { queryData: { roleName: 'org_agent', search_keyword: agentsState.searchKeyword }, optionData: agentsState.optionData }, onCompleted: (data) => { const currentUserId = userData?.user_id; const preparedData = data?.getOrganizationUsers?.data?.map((org_user) => { let title = org_user?.user?.first_name || org_user?.user.last_name ? getUserFullName(org_user?.user?.first_name, org_user?.user?.last_name) : org_user?.user?.email; if (org_user?.user?.id === currentUserId) { title += ' (You)'; } return { ...org_user, key: org_user?.id, title }; }) || []; setAgentsState((prevState) => ({ ...prevState, data: agentsState.optionData.offset === 0 ? preparedData : [...prevState.data, ...preparedData], metaData: data?.getOrganizationUsers?.meta_data || {}, loading: false, loaded: true })); }, onError: (error) => { console.error(error); setAgentsState((prevState) => ({ ...prevState, loading: false })); } }); const updateQueryData = useDebounce((value) => { setAgentsState((prev) => ({ ...prev, loading: true, searchKeyword: value, data: [], optionData: { ...prev.optionData, offset: 0 }, metaData: {} })); }, 500); const handleContentChange = (content, delta, source, editor) => { if (allowMention && source === 'user') { const cursorPosition = editor.getSelection()?.index; if (cursorPosition) { const textBeforeCursor = editor.getText(0, cursorPosition); const atIndex = textBeforeCursor.lastIndexOf('@'); const spaceIndex = textBeforeCursor.indexOf(' ', atIndex); if (atIndex > -1 && spaceIndex < 0) { const wordEnd = textBeforeCursor.length; const searchTerm = textBeforeCursor.substring(atIndex + 1, wordEnd); setCursorIndex({ startText: atIndex, endText: wordEnd }); updateQueryData(searchTerm); setShowMentionList(true); const bounds = editor.getBounds(cursorPosition); setMentionListPosition({ top: bounds.bottom, left: bounds.left }); } else { setShowMentionList(false); } } } onChange(content); }; const handleSelectMention = (mention) => { setMentionedIds((prev) => [...prev, mention.id]); const editor = editorRef.current.getEditor(); const range = editor.getSelection(true); if (range) { updateQueryData(''); editor.deleteText(cursorIndex.startText, cursorIndex.endText); editor.clipboard.dangerouslyPasteHTML( cursorIndex.startText, `<p><strong id='${mention.id}'>@${mention.title}</strong></p>` ); setShowMentionList(false); onChange(editor.root.innerHTML); } }; useEffect(() => { const handleClickOutside = (event) => { if (quillContainerRef.current && !quillContainerRef.current.contains(event.target)) { setShowMentionList(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); useEffect(() => { if (editorRef.current) { const editor = editorRef.current.getEditor(); if (editor && editor.container) { quillContainerRef.current = editor.container; } } }, [editorRef]); useEffect(() => { getAgents(); }, []); const modules = { toolbar: { container: [ [{ header: [1, 2, false] }], ['bold', 'italic', 'underline', 'strike', 'blockquote'], [({ list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' })], ['link', 'image', 'video'] ] } }; const formats = [ 'header', 'bold', 'italic', 'underline', 'strike', 'blockquote', 'list', 'bullet', 'indent', 'link', 'image', 'video' ]; const editorClassName = toolbarBottom ? 'editor-toolbar-bottom' : ''; return ( <div className={`react-quill-editor ${editorClassName} relative`}> <ReactQuill forwardedRef={editorRef} theme="snow" value={value} onChange={handleContentChange} readOnly={readOnly} modules={modules} formats={formats} placeholder={placeholder} /> {showMentionList && ( <div className="absolute z-10 mt-1 bg-white rounded border border-gray-300 shadow-lg" style={{ top: mentionListPosition.top, left: mentionListPosition.left }} > {size(agentsState.data) > 0 && agentsState.data.map((mention) => ( <div key={mention.id} className="px-4 py-2 cursor-pointer hover:bg-blue-100" onMouseDown={(e) => { e.preventDefault(); handleSelectMention(mention); }} > {mention.title} </div> ))} </div> )} </div> ); }; export default AppEditor;
const loadReactQuill = async () => { const { default: RQ } = await import('react-quill'); const Parchment = RQ.Quill.import('parchment'); const Block = Parchment.query('block'); class ButtonBlot extends Block { static create(value) { const node = super.create(value); node.setAttribute('class', 'button-class'); node.setAttribute('style', 'button-style'); return node; } } ButtonBlot.blotName = 'button'; ButtonBlot.tagName = 'button'; RQ.Quill.register(ButtonBlot); const reactQuillWithRef = ({ forwardedRef, ...props }) => <RQ ref={forwardedRef} {...props} />; return reactQuillWithRef; };
The text was updated successfully, but these errors were encountered:
Did you solve this problem?
Sorry, something went wrong.
No branches or pull requests
Issue Summary:
Unable to insert html into Quill React Component.
Environment:
React version: "18.2.0"
react-quill: "2.0.0"
next:"14.1.0"
Code snippet:
My Component file:
I have alos tried with parchment package but this also not work.
Here the Code sinppet
The text was updated successfully, but these errors were encountered: