TinyMCE Disappears after destroyed() event

I have TinyMCE working on static page with script that looks like this:

import "tinymce/tinymce.min.js"
import "tinymce/themes/silver/theme.js"
import "tinymce/icons/default/icons.js"

window.addEventListener('load', (event) => {
	tinymce.init({
	  selector: '#mytextarea',
	  inline: true,
	  skin: false,
	  content_css: 'css/app.css'
	});
});

and in the template:

<form method="post">
  <div id="tinymce">Hello, World!</div>
</form>

This works as expected.

When trying in a liveview, the only thing I’ve been able to get to work is:

app.js

...
import {Socket} from "phoenix"
import LiveSocket from "phoenix_live_view"
import NProgress from "nprogress"
import "tinymce/tinymce.min.js"
import "tinymce/themes/silver/theme.js"
import "tinymce/icons/default/icons.js"

let Hooks = {}
Hooks.TinyMCE = {
  mounted() {
  	console.log("mounted")
		tinymce.init({
		  selector: '#tinymce',
		  inline: true,
		  skin: false,
		  content_css: 'css/app.css'
		});
  }
}

let liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks, params: {_csrf_token: csrfToken}})
...

and then in the form component:

<h2><%= @title %></h2>
<%= f = form_for @changeset, "#",
  id: "post-form",
  phx_target: @myself,
  phx_change: "validate",
  phx_submit: "save",
  phx_update: "ignore" %>

  <div id="tinymce" phx-hook="TinyMCE">Hello, World!</div>
  <%= label f, :title %>
  <%= text_input f, :title %>
  <%= error_tag f, :title %>

  <%= textarea f, :body %>

  <%= submit "Save", phx_disable_with: "Saving..." %>
</form>

This only works on the first reloading after updating app.js then does not work on subsequent reloads.

Any tips on what is going wrong?

Every time the lv updates, the element(s) TinyMCE is attached to are being replaced.

Could try wrapping the textarea in an element with phx-update="ignore"

1 Like

Thanks @harmon25. That helped a little bit, but it still disappears after canceling the modal and clicking new posts.

I made a bare minimal repo with TinyMCE working on the static home page and then attempting with LiveView on localhost/page-live. The TinyMCE works on the first mount, but not on subsequent ones.

Off to bed, will continue in the morning!

The solution was to remove tinymce and re init wrapped in a set timeout on destroyed() life-cycle callback:

Hooks.TinyMCE = {
	mounted() {
		tinymce.EditorManager.init({
			selector: "#tinymce",
			inline: true,
			skin: false,
			content_css: 'css/app.css'
		});
	},
	destroyed(){ 
		tinymce.remove();
		setTimeout(function() {
		  tinymce.init({
			  selector: "#tinymce",
			  inline: true,
			  skin: false,
			  content_css: 'css/app.css'
		  });
	  }, 1);
	}
}

Refs:

1 Like