react-quill: Inserting Text into the editor with a custom button results in error on keystroke

Quill version

  • master

Given a toolbar witha custom handler in the modules function

      toolbar: {
        container: [
          ['custom']
        ],
        handlers: {
          "custom": function () {
        
              this.quill.insertText(this.quill.getSelection().index, 'Hello', 'link', 'https://world.com');
              console.log(this.quill.getText())
          }
        }
      }

When you click the button it does correctly insert the text, but when you click in the editor you get: The given range isn't in document. Every time you try to type normally. Removing the item in the toolbar makes this stop

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 2
  • Comments: 17

Most upvoted comments

Use componentDidMount and ref, and remove handlers from modules:

modules() {
  return {
    toolbar: {
      container: [
        [
        'custom'
        ]
      ]
    }
  }
}

handleCustomToolbarButton() {
  const quill = this.quillRef.getEditor()

  quill.insertText( quill.getSelection().index, 'Hello', 'link', 'https://world.com' )
  
  console.log( quill.getText() )
}

componentDidMount() {
    const toolbar = this.quillRef.getEditor().getModule('toolbar')
    
    toolbar.addHandler( 'custom', ::this.handleCustomToolbarButton )
}

render() {
    return (
      <ReactQuill
        ref={(el) => this.quillRef = el}
        className={classes.rteParent}
        theme={`snow`}
        value={value || text}
        onChange={this.handleChange}
        modules={this.modules()}
        formats={this.formats()}
      >
          <div className={classes.rteEditZone}/>
      </ReactQuill>
    )
}

in my case , it worked when i delete this from[ codepen example] (https://codepen.io/alexkrolick/pen/gmroPj?editors=0010) and added componentDidMount like @undermuz comment

 <div 
        key="editor"                     
        ref="editor"
        className="quill-contents"                     
/>

my complete code ( using server render)

import React from 'react';
import 'react-quill/dist/quill.snow.css';

const CustomToolbar = () => (
  <div id="toolbar">
    <select className="ql-header">
      <option value="1"></option>
      <option value="2"></option>
      <option selected></option>
    </select>
    <button className="ql-bold"></button>
    <button className="ql-italic"></button>
    <select className="ql-color">
      <option value="red"></option>
      <option value="green"></option>
      <option value="blue"></option>
      <option value="orange"></option>
      <option value="violet"></option>
      <option value="#d0d1d2"></option>
      <option selected></option>
    </select>
    <button className="ql-insertStar">
      <span className="octicon octicon-star">★</span>
    </button>
  </div>
);

function insertStar() {
  const cursorPosition = this.quill.getSelection().index;
  this.quill.insertText(cursorPosition, '★');
  this.quill.setSelection(cursorPosition + 1);
}


const modules = {
  toolbar: {
    container: '#toolbar',
    handlers: {
      'insertStar': insertStar,
    }
  }
};

const formats = [
  'header', 'font', 'size',
  'bold', 'italic', 'underline', 'strike', 'blockquote',
  'list', 'bullet', 'indent',
  'link', 'image', 'color',
];

class Editor extends React.Component {

  constructor(props) {
    super(props);
    this.state = {editorHtml: ''};
    if (typeof window !== 'undefined') {
      this.ReactQuill = require('react-quill');
    }
  }

  handleChange(html) {
    this.setState({editorHtml: html});
  }

  componentDidMount() {
    const toolbar = this.quillRef.getEditor().getModule('toolbar');
    toolbar.addHandler('insertStar', insertStar);
  }

  render() {
    const ReactQuill = this.ReactQuill;

    if (!ReactQuill) {
      return null;
    }

    return (
      <div className="text-editor">
        <CustomToolbar/>
        <ReactQuill
          ref={(el) => this.quillRef = el}
          onChange={this.handleChange.bind(this)}
          placeholder={this.props.placeholder}
          modules={modules}
          formats={formats}
          theme={'snow'}
        >
        </ReactQuill>
      </div>
    );
  }
}

export default Editor;