Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turbo + TinyMCE — doesn't reinit the editor after a Turbo interaction #308

Open
jasonfb opened this issue Oct 7, 2023 · 8 comments
Open

Comments

@jasonfb
Copy link

jasonfb commented Oct 7, 2023

Symptom:
Although TinyMCE inits once after a page load, if you make a Tubro interaction (either a whole page render or a frame replacement), the TinyMCE widget does not reinitialize to the textarea after your first Turbo interaction.
tinymce-with-turbo2

Note: there are various suggestions on setting up TinyMCE, but I have the most basic in my <head>

<head>
<%= tinymce_assets %>

    <script>
      TinyMCERails.configuration.default = {
        selector: "textarea.tinymce",
        cache_suffix: "?v=6.7.0",
        menubar: "insert view format table tools",
        toolbar: ["bold italic | link | undo redo | forecolor backcolor | bullist numlist outdent indent | table | uploadimage | code"],
        plugins: "table,fullscreen,image,code,searchreplace,wordcount,visualblocks,visualchars,link,charmap,directionality,nonbreaking,media,advlist,autolink,lists",
        images_upload_url: "/uploader/image"
      };
    </script>
<!-- more head content -->
</head>

Then you of course attach class tinymce to your textareas. This works for the 1st pickup, but after navigating with Turbo interactions, TinyMCE stops working.

@jasonfb
Copy link
Author

jasonfb commented Oct 7, 2023

Ok, what's going on here is a little tricky, important to grok before moving forward:
• TinyMCE doesn't seem to like to be re-inited after it exists in memory, therefore, it must be unloaded before the turbo interaction and reloaded after the turbo interaction.

To do this, here's what I've done

I am using a JSBundling app with the Sprockets pipeline, so my app/application/javascript.js contains this:

import "./tinymce_init"

Then I have a file app/application/tinymce_init.js with this content:

const reinitTiny = () => {
  console.log("connecting tiny...")
  console.log(tinymce);


  tinymce.init({
    selector: 'textarea.tinymce', // Add the appropriate selector for your textareas
    // Other TinyMCE configuration options
  });
}

window.addEventListener('turbo:before-fetch-response', () => {
  tinymce.remove();
  tinymce.init({selector:'textarea.tinymce'});
})
window.addEventListener('turbo:frame-render', reinitTiny)
window.addEventListener('turbo:render', reinitTiny)

(As this is all global code, you can easily put it into the <head> of your DOM, but I have done it this way just to keep the head clean)

Please note that the above code works with page re-renders and frame renders, I have not tested stream renders.

After this fix, TinyMCE re-initializes appropriately between Turbo interactions

tinymce-with-turbo4

@wvengen
Copy link

wvengen commented Nov 3, 2023

As a sidenote: with Turbo, you really need to put the Javascript in the head. Putting it in the body gives strange problems (where Turbo inserts the scripts tags on navigation).

@dgm
Copy link

dgm commented Jun 21, 2024

I just took the initialization code and put it into a stimulus controller connect() method, and added the tinymce.remove(); at the beginning. This forces a reload whenever the stimulus controller is loaded, only in pages that use it.

@yjchieng
Copy link

I just took the initialization code and put it into a stimulus controller connect() method, and added the tinymce.remove(); at the beginning. This forces a reload whenever the stimulus controller is loaded, only in pages that use it.

I am doing something like the below. Seems to work, but there is some 2-3 sec loading delay once in a while when navigate away from the page that has editor.
Still trying to find a better way.

export default class extends Controller {
    connect() {
        tinymce.init({...});
    }
    disconnect() {
        tinymce.remove();
    }
}

@seanwmitchell
Copy link

Thanks @jasonfb the fix worked for me

@braulio
Copy link

braulio commented Oct 16, 2024

Hello! Do we have to solve this problem?

@seanwmitchell
Copy link

yes @braulio the fix above works

@braulio
Copy link

braulio commented Oct 16, 2024

I tested it and it didn't work. Could you send me a complete example, as nothing I've done has worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants