Search code examples
javascriptquillngx-quill

Undefined blot inserted after embedding custom inline blot in Quill editor


I am working on twitter like user mentions for Quill editor.

My custom blot code is

import Quill from 'quill';

const Base = Quill.import('blots/inline');

export default class MentionBlot extends Base {
static create(data) {
  const node = super.create(data.name);
  node.innerHTML = `@${data.name}`;
  node.setAttribute('contenteditable', false);
  node.setAttribute('name', data.name);
  node.setAttribute('id', data.id);
  return node;
}

MentionBlot.blotName = 'usermention';
MentionBlot.tagName = 'aumention';

I am displaying users list in dropdown. When ever one of the user name is clicked, I am embedding the user as @User in quill editor.

this is the click event I had written for it. The thing I am doing here is I am replacing the text user entered after @ with the custom Inline blot.

  searchResult.forEach(element => {
    element.addEventListener('click', e => {
      e.preventDefault();
      e.stopPropagation();

      const quillEditor = window.editor;
      const content = quillEditor.getText();

      const quillRange = quillEditor.selection.savedRange; // cursor position
      if (!quillRange || quillRange.length != 0) return;
      const cursorPosition = quillRange.index;
      let mentionStartAt = 0;
      let lengthToBeDeleted = 0;
      for (let i = cursorPosition - 1; i >= 0; --i) {
        const char = content[i];
        if (char == '@') {
          mentionStartAt = i;
          lengthToBeDeleted += 1;
          break;
        } else {
          lengthToBeDeleted += 1;
        }
      }
      const data = {
        name: element.innerHTML,
        id: element.getAttribute('id')
      };

      quillEditor.deleteText(mentionStartAt, lengthToBeDeleted);
      quillEditor.insertEmbed(mentionStartAt, 'usermention', data, 'api');
      const cursorAfterDelete =
        quillEditor.selection.savedRange.index + element.innerHTML.length;

      quillEditor.insertText(cursorAfterDelete + 1, ' ', 'api');
      quillEditor.setSelection(cursorAfterDelete + 2, 'api');
      quillEditor.format('usermention', false, 'api');

    });
  });
}

Until here, everything is working like charm but the issue I am facing is after inserting the embed usermention blot, If the user enters Enter button on Keyboard to go to new line, Quill's handleEnter() function is getting triggered and it is inserting @undefined usermention blot to the editor.

After executing the above function, my editor state is this. Editor before hitting enter

When I press enter to go to new line, this is the debug state of handleEnter() function - Quill

handleEnter() debugger state

@undefined usermention got inserted into the editor. I want the user to enter new line.

@undefined in Quill editor

When the user presses Enter, I understood that quill.format() is returning usermention:true. But if the user presses Enter after typing few more characters, it is taking him to new line and in this case quill.format() is empty.

Can some one please help me in this regard. Thank you.


Solution

  • Reference: https://quilljs.com/docs/modules/keyboard/

    Handling enter with Quill keyboard binding is easier than adding addLister to it, the below method helps you to handle whenever the enter event fires in the quill editor

    var quill = new Quill('#editor', modules: {
    keyboard: {
      bindings: bindings
    }}});
    
    
    var bindings = {
      handleEnter: {
        key: '13', // enter keycode
        handler: function(range, context) {
           //You can get the context here
        }
      }
    };
    

    I hope the above answer suits your needs.