Add A Dropdown List in Suneditor React Using Custom Plugin

Merge Tags Or Insert Variables Can Easily Be Listed For The User To Choose From

In almost all of the text editors available for React JS adding your own dropdown list is not an easy task. In a React app I was using suneditor, and I needed to add my own dropdown list for the users to select a merge tag from, but I couldn’t find a way from their documentation. The only option was to use their custom plugin.

From suneditor’s documentation on custom plugin, I found a way to add my own list. Here’s how it can be done in two steps.

Add A Custom Plugin Code

Copy and paste the below code in a separate file, with changes such as file and plugin names. I’m naming the file merge_tag_plugin.js and the plugin namemerge_tag. Export this. (Alternatively you can use it at the same place you’re using suneditor)

const mergeTag = {
  // @Required
  // plugin name
  name: 'merge_tag',

  // @Required
  // data display
  display: 'submenu',

  // @Required
  // add function - It is called only once when the plugin is first run.
  // This function generates HTML to append and register the event.
  // arguments - (core : core object, targetElement : clicked button element)
  add: function (core, targetElement) {

    // Generate submenu HTML
    // Always bind "core" when calling a plugin function
    let listDiv = this.setSubmenu.call(core);

    // You must bind "core" object when registering an event.
    /** add event listeners */
    var self = this;
    listDiv.querySelectorAll('.se-btn-list').forEach(function (btn) {
      btn.addEventListener('click', self.onClick.bind(core));
    });

    // @Required
    // You must add the "submenu" element using the "core.initMenuTarget" method.
    /** append target button menu */
    core.initMenuTarget(this.name, targetElement, listDiv);
  },

  setSubmenu: function () {
    const listDiv = this.util.createElement('DIV');
    // @Required
    // A "se-submenu" class is required for the top level element.
    listDiv.className = 'se-submenu se-list-layer';
    listDiv.innerHTML = '<div class="se-list-inner se-list-font-size"><ul class="se-list-basic"><li><button type="button" class="se-btn-list" value="{firstName}">{firstName}</button></li><li><button type="button" class="se-btn-list" value="{lastName}">{lastName}</button></li></ul></div>'

    return listDiv;
  },
  onClick: function (e) {
    const value = e.target.value;
    const node = this.util.createElement('span');
    this.util.addClass(node, 'se-custom-tag');
    node.textContent = value;

    this.insertNode(node);
    const zeroWidthSpace = this.util.createTextNode(this.util.zeroWidthSpace);
    node.parentNode.insertBefore(zeroWidthSpace, node.nextSibling);

    this.submenuOff();
  }
};

export default mergeTag

Notice setSubmenu method. It’s there in lastDiv.innerHTML we’re giving the our list of merge tags ({firstName} and {lastName}).

Pass Custom Plugin Name In setOptions

Import the plugin into the file where you’re using suneditor and pass it along the setOptions plugins as shown below.

import mergeTag from "../../merge-tag-plugin";

//...

<SunEditor
    onChange={handleInputChange}
    placeholder={"Insert Text Here"}
    showToolbar={true}
    setOptions={{
        height: 200,
        plugins: [
            mergeTag
            //...
        ]
    }} />

Pass Custom Object setOptions buttonList

This object will link up our custom plugin code based on the name we used (merge_tag). Also, the innerHTML is what will show as the name of the dropdown click.

<SunEditor
    onChange={handleInputChange}
    placeholder={"Insert Text Here"}
    showToolbar={true}
    setOptions={{
        height: 200,
        plugins: [
            mergeTag
        ],
        buttonList: [
                {
                    name: 'merge_tag',
                    dataCommand: 'merge_tag',
                    buttonClass: '',
                    title: 'Merge Tag',
                    dataDisplay: 'submenu',
                    innerHTML: '<span>Merge Tag</span>',
                }
                //...
            ],
        ]
    }} />

And it’s done! The editor will look and behave something like this:

(Note that you might need to import and add default plugins and also provide additional buttonList items for all of the toolbar to appear beside the custom plugin.)