tinyMCE webcomponent does not fire events with lit-html

489 Views Asked by At

I have implemented tinyMCE webcomponent with lit-HTML. Editor renders well, but events never fire.

import { LitElement, html, css } from 'lit-element';
import '@tinymce/tinymce-webcomponent';


render() {
    return html`
      <tinymce-editor
        api-key="n***************************8"
        @change=${()=>this.handleChangeEvent}
      ></tinymce-editor>
    `;
  }


handleChangeEvent(e){
    // this never fires
  }

Adding a listener to the editor once HTML has rendered also does not work.

firstUpdated() {
    this.editor = this.shadowRoot.getElementById('editor');
    this.editor.addEventListener("change", (e)=>this.handleEvent(e));  // this also never fires
  }

Any ideas about ways to resolve ?

1

There are 1 best solutions below

2
On

This isn't an issue with Lit, it's functionality missing from <tinymce-editor> as it doesn't fire the change event you're subscribing to.

It appears to have a really weird implementation of synthetic events - I don't think the component actually fires any composed events (though some browser ones might get through).

Instead of <tinymce-editor> firing an event called change, it appears to look for an attribute called on-Change (according to the docs, but the source lowercases it) that expects a string. It then looks up a function with that name using @ephox/katamari Resolve.

Basically:

<tinymce-editor on-Change="handleChangeEvent"

Will look for window.handleChangeEvent and if it finds that name it executes. It has some handling for scope - I think you can pass a parent object and call a named instance method on it.

Lit could pass the actual function reference:

<tinymce-editor .on-Change=${e => handleChangeEvent(e)}

But I don't think this will work with <tinymce-editor> due to how the function is resolved. It only works with globally defined function names.

However, you can get the source of their component and rip all this out for your own implementation. Mostly it just appears to be a lot of wrapper to hide loading their JS from a CDN with an API key, but you can just load that too.

Then replace their on-* weirdness with this.dispatchEvent and as long as you include composed: true it will fire the events you expect.