How to get the Editor integrated into Drupal

Install package

npm install --save @bolt/components-editor Then add to .boltrc.js file like so.

Add to a Drupal Template file

First, find out the JS & CSS files that are used to display the content we want to edit. This will most likely simply be from the Drupal Libraries that are loaded for the current page from the theme. We need to get the variables styles, which is an array of strings to CSS files; and scripts which is the same but for JS.

Be sure to check it with CSS & JS Aggregation on & off!
{# Just some example content #}
{% set content %}
  <button type="button" class="e-bolt-text-link">
    Hello World!
  </button>
{% endset %}

{% if userLoggedIn %}
  {# get these strings from Drupal based on what Drupal Libraries are loaded #}
  {% set styles = ['/build/bolt-global.css'] %}
  {% set scripts = ['/build/bolt-global.js'] %}

  {# whatever id is needed to save this back to Drupal; probably a Paragraph id! #}
  {% set id = 'probably-paragraph-id' %}

  {% include '@bolt-components-editor/editor.twig' with {
    styles: styles,
    scripts: scripts,
    content: content,
    id: id,
  } only %}
{% else %}
  {# if user is not logged, then just render `content`, no need to pass into Editor template! #}
  {{ content }}
{% endif %}

Listen for "editor:save" event

Here's some JavaScript that will listen for the editor:save event after the user clicks the "Save" button. This is when you should save the HTML to Drupal.

document.querySelectorAll('.js-pega-editor').forEach((pegaEditor) => {
  pegaEditor.addEventListener('editor:save', (event) => {
    console.log('An editor just saved and we have new HTML to send to Drupal!', {
      id: event.detail.id,
      html: event.detail.html,
      editorElement: event.target, // same as `pegaEditor`
    });
  });
});

Handling editor save

Assign a function to window.__handleEditorSave that will run the Drupal Save process and resolve with an object of {ok: true/false, message: "Error: could not...." }.

Note that we are not returning an error/reject, merely a {ok: false} if the Drupal http request fails. The included message will be displayed as an alert.

Below is the example handler, which should be over-written on the window. The shouldThisFailDemo var is toggleable to simulate both events. The setTimeout() is only necessary for simulating async, the production function should not include this.

//@TODO: actual Drupal http request code
window.__handleEditorSave = () => {
  return new Promise((resolve, reject) => {
    // faking async delay
    setTimeout(() => {
      if (shouldThisFailToDemo) {
        console.log('exampleHandleEditorSave failed');
        resolve({
          ok: false,
          message: 'This is a demonstration of how to fail the save'
        });
      } else {
        console.log('exampleHandleEditorSave ok!');
        resolve({
          ok: true,
          message: 'Saved ok!',
        });
      }
    }, 2000);
  })
}