Getting started with TinyMCE in Nuxt: A step-by-step guide

I need to incorporate this script into my Nuxt code:

<script>
  tinymce.init({
    selector: "#mytextarea",
    plugins: "emoticons",
    toolbar: "emoticons",
    toolbar_location: "bottom",
    menubar: false
  });
</script>

I can simply place it within my component's template body (This script must be inside <body> rather than <head>) like so:

https://i.stack.imgur.com/3a4xS.png

and surprisingly, it functions. However, there are two issues:

  1. It appears unattractive
  2. It lacks dynamism. For instance, I cannot dynamically bind selector to a prop or data property! It has to be hardcoded.

Therefore, I am seeking advice on how to properly integrate such scripts into my Nuxt project.

Answer №1

  1. I highly question the effectiveness of this method. Vue consistently disregards any <script> tags in templates and displays an error message:

Templates should solely focus on mapping the state to the UI. Avoid including tags with side effects in your templates, such as <script>, as they will not be interpreted.

  1. There is no necessity to include this in the template. It is simply normal JS code that can be executed as part of the component lifecycle. Below is a very basic component wrapper that integrates TinyMCE into a Vue app.

However, I do not recommend doing this manually and suggest utilizing the official Vue wrapper (docs) - utilize v3 for Vue 2. The official integration manages all edge cases like component activation/deactivation (when used with <keep-alive>) and proper cleanup when the component is destroyed to prevent memory leaks

const ed = Vue.component("MyEditor", {
  props: ["id", "value"],
  template: `
    <div>
      <textarea :id="id" :value="value"></textarea>
    </div>
  `,
  mounted() {
    const me = this;
    window.tinymce.init({
      selector: "#" + this.id,
      plugins: "emoticons",
      toolbar: "emoticons",
      toolbar_location: "bottom",
      menubar: false,
      setup: function (editor) {
        editor.on("change input undo redo", function () {
          me.$emit('input', editor.getContent({format: 'text'}))
        });
      }
    });
  }
});

Demo

Nuxt

As TinyMCE is completely JS rendered, it is not logical to execute it during server-side rendering. In fact, the above code will not operate on the server at all since there is no window variable. Use Nuxt's <client-only> component to exclusively render the editor on the client side...

UPDATE: On the contrary, the mounted lifecycle hook is not triggered during SSR so perhaps this method will function adequately even without the use of <client-only>

Answer №2

In the response that was approved, it was suggested to rely on the official vue package. However, even with the official package, I encountered several issues when integrating it into Nuxt.

Below is a detailed guide on how I successfully got it to work using the following versions:

    "tinymce": "^5.10.3",
    "@tinymce/tinymce-vue": "^3.2.8",
    "vue": "^2.6.11",
    "nuxt": "2.15.8",

The tinymce-vue package requires the availability of tinymce. You can either install it via npm as shown above, or opt for the cloud-hosted version (refer to Prerequisites here).

Challenges Specific to Nuxt

Ensure that the component is enclosed within the <client-only> tag to prevent SSR errors.

If you are self-hosting the tinymce package, make sure to import it only on the client-side to avoid errors like the following:

[Vue warn]: Failed to resolve async component: ... Reason: ReferenceError: navigator is not defined

You can accomplish this by utilizing require and wrapping them around if (process.client) {.

Example:

if (process.client) {
  require('tinymce/tinymce')
  require('tinymce/themes/silver')
  require('tinymce/icons/default')
  require('tinymce/plugins/lists') // repeat for any editor plugins used
}

import Editor from '@tinymce/tinymce-vue'

At this stage, the editor should load on your page, but the styles may not load properly.

To address this issue, add

require('tinymce/skins/ui/oxide/skin.min.css')
after the other requires.

Although the styles are now fixed, the tinymce theme may still attempt to fetch additional CSS files like mobile and min versions independently, leading to network errors.

Example:

404 http://localhost:3000/_nuxt/skins/ui/oxide/content.min.css
404 http://localhost:3000/_nuxt/skins/ui/oxide/skin.min.css

For content: You can either duplicate the file in the static folder with the same path or customize using the content_css setting (within the Vue component init options).

For skin: Considering it was already provided as a module, set skin: false in the Vue component init settings.

UPDATED 2022-11-29: Typo Correction

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When working with Function components in NextJS, it's important to note that they cannot be assigned refs directly. If you're trying to access a ref within a Function component, you

I'm having an issue with wrapping a card component using the Link component from 'next/link'. Instead of redirecting me to the desired link when I click the card, I receive a warning that says 'Function components cannot be given refs. ...

Display a pop-up upon clicking a button

I've created a custom popup form using Flodesk and added the corresponding Javascript Snippet to my website just before the closing head tag. <script> (function(w, d, t, h, s, n) { w.FlodeskObject = n; var fn = function() { (w[n] ...

Tips for using a JavaScript variable in a PHP file on WordPress

As a newcomer to Wordpress, I am trying to navigate the Theme Editor. Within it, I found a javascript file that looks like this: const isMenuOpen = false; function toggleMenu() { alert("toggle"); isMobileMenuOpen = !isMobileMenuOpen; } ...

Embed images within the JavaScript bundle

Here is my scenario: I have developed a components library for React. Within this library, there is a package bundled with Rollup that contains various assets, including a GIF picture used in one of the components. The specific component utilizing this p ...

What is the best way to separate one dropdown area from another dropdown area?

I have two dropdown menus where, when an option with the value "other" is clicked, it generates a text area just below the dropdown menu. Both sections are functioning correctly, but I had to create separate parent wrappers for each in order to do so. How ...

Unable to install react-dom/test-utils using npm

I recently included two libraries in my package.json "devDependencies": { ... "react-dom/test-utils": "*", "react-test-renderer/shallow": "*" }, These were recommended by the React documentation to align with version 16 of the React ecosy ...

Trouble uploading an audio blob as a base64 string using Google Drive API with the drive.files.create method - File ID could not be located

My current challenge involves sending an audio blob to a specific Google Drive folder. To accomplish this, I convert the blob into a file before initiating the transfer process. However, I have encountered an error from the beginning: Error: File not fo ...

Error: Unable to access the 'questionText' property as it is undefined

I encountered an error message stating that my "questionText" could not be read or is not defined. The issue seems to arise in the first code block where I use "questionText", while the intention is to drag it in the second code block. Is there a mistake ...

The Mongoose query for the id field retrieves both the id and _id values

Within my Mongoose schema, there is a specific field named id which holds a unique identifier for each document. This operates using the same system as the standard _id field as shown below: var JobSchema = new mongoose.Schema({ id: { type:String, requi ...

The issue of undefined database columns arises when attempting to transmit data from an HTML form to a MySQL database via Express

My primary objective is to develop a RestAPI using Node.js and test it in a small HTML application. With the guidance of my instructor, I successfully created the RestAPI based on an example and customized it to work with my own MySQL database. Testing ea ...

Adjusting the selected state of an HTML/CSS checkbox with JavaScript

After downloading a theme with a tailored switch component that replaces the standard checkbox functionality, I noticed that the 'checked' status of the underlying checkbox does not change upon click or touch events. Here is the HTML structure: ...

Python code allowing users to navigate back to the previous page while retaining elements

After my script scrapes the page, it automatically clicks a button if a new element meeting certain criteria is found. Everything works perfectly when there is only one element, but an issue arises when the button click leads to a new page opening. If ther ...

Mapping an array using getServerSideProps in NextJS - the ultimate guide!

I'm facing an issue while trying to utilize data fetched from the Twitch API in order to generate a list of streamers. However, when attempting to map the props obtained from getServerSideProps, I end up with a blank page. Interestingly, upon using co ...

Utilize the power of jQuery for form validation by combining the errorPlacement and showErrors functions

I am currently attempting to implement validation using the Jquery .validate plugin. Unfortunately, I have encountered an issue where I am unable to utilize both the errorPlacement and showErrors methods simultaneously. If you'd like to see a demons ...

Using the inline calendar feature of Bootstrap 3 Datepicker to easily select and capture dates

I've been struggling to extract the selected date from my bootstrap 3 datepicker, and despite attempting to follow the documentation, I still can't grasp it. Here's what I tried: <div id="datetimepicker"> <i ...

Retrieving information from a JSON object in Angular using a specific key

After receiving JSON data from the server, I currently have a variable public checkId: any = 54 How can I extract the data corresponding to ID = 54 from the provided JSON below? I am specifically looking to extract the values associated with KEY 54 " ...

Is it possible to customize the width of text color alongside a progress bar?

My Bootstrap 4 Website contains the following HTML code snippet: <div class="container"> <div class="row"> <div class="col-md-6 mx-auto> <h2>Example heading text</h2> <h6>Example subh ...

Replace the typical bootstrap text class with stylish and modern google material icons

As a newcomer to the world of javascript, I acknowledge that my approach may not be ideal... I'm attempting to modify the color of a material icon upon clicking it. Essentially, I want to toggle it on and off. The challenge lies in the code's in ...

Activate Jquery as the user navigates through it with scrolling

Is there a way to activate a JQuery event when the user first scrolls over a particular div? I attempted to utilize waypoint for this purpose, but unfortunately, it did not work as expected. Below is the code I used with no errors: var waypoints = $(&apo ...

What is the most effective method for sorting through vast amounts of data with Javascript, React, and Redux?

Currently, I am working with a minimum JSON data set of 90k [...] and utilizing the .filter method. Everything is functioning correctly without any issues, however, from a performance standpoint, I am curious about potential improvements. Any suggestions o ...