Incorporating Tinymce into a dialog with Vuejs & Vuetify may necessitate a refresh

I have implemented tinymce as a component for creating and editing articles

In addition, I am using vuetify along with the v-dialog component, and all my form fields are within this modal

However, each time I change the instance of the tinymce component, I need to reload the component by changing the key property

For a clearer understanding, here is an example

I have set up a web service in a development environment

id: [email protected]

pass: p@ssw0rd!

To replicate the issue :

  • Visit the "Articles" section
  • Open the "Create an article" modal (The editor is located at the bottom)
  • Close the dialog
  • Then, open the editing modal using the mdi-pencil icon

At this point, the editor will be empty, and you will need to click on "Relancer l'éditeur" to load the content

The same applies to the "Portfolio" section

Feel free to create, edit, delete as needed, it's a development environment

Below is an overview of my code (simplified) :

modal.vue (The main component of the modal)

<template>
    <div :style="`z-index:${index} !important; display: inherit`">
        <v-dialog v-model="dialog" persistent transition="dialog-top-transition" :hide-overlay="hideOverlay"
            :max-width="maxWidth" overlay-color="primary">
            <v-form v-model="formValidation" ref="form" lazy-validation enctype='multipart/form-data'
                :retain-focus="false"gt;
                <slot name="content"></slot>
            </v-form>
        </v-dialog>
        <div style="display: inherit" @click="dialog = true">
            <slot></slot>
        </div>
    </div>
</template>

create.vue

<template>
    <modal title="Create an article" description="To create an article, fill in the fields below: "
        v-on:submit="submit" ref="modal" show-cancel label="Save"&rt;
        <slot></slot>
        <template v-slot:content>
            <v-btn @click="reload">Reload the editor</v-btn>
            <v-col cols="12" @focusin.stop>
                <editor id="create-article" :key="key" :api-key="apiKey" v-model="request.content"
                    :init="editorOptions"></editor>
            </v-col>
        </template>
    </modal>
</template>

<script>
import {editorOptions, apiKey} from "&/plugins/editor";
import {generateRandomKey} from "@/utils";

export default {
    name: "create",
    data() {
        return {
            key: '',
            apiKey,
            editorOptions,
            request: {
                content: '',
            },
        }
    },
    methods: {
        submit() {
        },
        reload() {
            this.key = generateRandomKey();
        },
    }
}
</script>

Update :

I have also attempted the following

mounted() {
    this.$nextTick(() => {
        this.$watch(
            () => this.$refs.modal.dialog,
            (v) => v ? this.reload() : null,
        )
    });
},

Thank you in advance for your assistance

Answer №1

After struggling for hours on end with the same issue, I finally found a solution that worked for me through a combination of different tactics:

The outer component with the dialog housing the TinyMCE editor had to be set with eager as True and Retain-focus as False.

<v-dialog
    v-if="someCondition"
    v-model="openEditorModal"
    max-width="600px"
    scrollable
    :retain-focus="false"
    @click:outside="closeEditorModal"
    @keydown="closeOnKeydown"
    :eager="true"
/>

The component wrapping the TinyMCE editor conditionally displays its content using v-if:

<MceEditor
  v-if="showMce"
  :inline="true"
  :content="someObject.text
  @change="someObjectChange($event)"
></MceEditor>

To delay the creation of the TinyMCE editor and destroy it when the wrapping component is unmounted:

  public mounted() {
    this.$nextTick(() => {
      setTimeout(() => {
        this.showMce = true;
      }, 3000);
    });
  }

  public beforeUnmount() {
    this.showMce = false;
  }

It may not be pretty, but it gets the job done.

Answer №2

To ensure separate states for each editor instance in Vue, it is recommended to set unique keys only once, typically during mounting. For example:

create.vue

mounted(){
  this.key = "editor-create"
}

edit.vue

mounted() {
  this.key = `editor-edit-${this.item.id}`
}

Alternatively, you can directly set the keys in the template:

<editor key="editor-create" ...></editor>
<editor :key="`editor-edit-${item.id}`" ...></editor>

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

Enhance your viewing experience with the Zoom feature that activates when

I recently noticed on that I am able to zoom/enlarge a photo by clicking on it. Is there a way for me to incorporate this feature without purchasing the entire theme? While I understand the theme is designed for purchase, I only need this specific functi ...

What is the best way to sort through an array using JavaScript?

Here's an array for you: values = ["10%", 1000, "5%", 2000] I'm looking to split this into two separate arrays like so: percentages = ["10%","5%"] numbers = [1000,2000] How can I achieve this using JavaSc ...

Tips for invoking the setState method via an onClick event the ES6 way

class BlogPost extends React.Component{ //getInitialState constructor(){ super(); this.onLike = this.onLike.bind(this); this.state = { like :0 } } onLike(){ this.setState({ li ...

JavaScript: Manipulating Data with Dual Arrays of Objects

//Original Data export const data1 = [ { addKey: '11', address: '12', value: 0 }, { addKey: '11', address: '12', value: 0 }, { addKey: '12', address: '11', value: 0 }, { addKey: &a ...

"Utilizing Vue-auth to Restrict Access to a Route Based on User Role - A Step-by-Step Guide

My initial Laravel application development involves using Vue-js in a single-page application (SPA). I am attempting to restrict access to a route (view-router) based on user roles. To manage roles, I am utilizing the spatie/laravel-permission package. ...

Tips for incorporating API-provided CSS values into AngularJS expressions for stylish card customization

I am in the process of creating unique Pokemon cards that pull data from an API. My question is, how can I apply specific CSS styling to each card directly from the API, similar to how I have utilized AngularJS to render the information? So far, I have su ...

How to dynamically delete React Router Link components after they have been clicked on?

When using React Router, how do I remove the div that contains a Link component or the Link component itself when it is clicked on and the routing is complete? For instance, consider an app structured in the following way: ==Header== ==Link1 Link2== Onc ...

No visible changes from the CSS code

As I create a small HTML game for school, I'm facing an issue with styling using CSS. Despite my efforts to code while using a screen reader due to being blind, the styling of an element isn't being read out as expected. The content seems to be c ...

looping through a collection of table rows using v-for

In a Vue app, I am facing an issue with rendering multiple table rows for each item in a collection. The current markup I have for rendering the table body is as follows: <tbody> <template v-for="item in collection"> <tr> < ...

An issue arose when trying to display React components within an Angular application

Attempting to incorporate React components into an Angular 7 application has been a challenge for me. While I have successfully rendered simple React components, I encountered the following error message (displayed in the browser console) when attempting t ...

Adding or Deleting Rows from Input Table

I'm in the process of creating a website that features an input table allowing users to easily add or remove rows at their discretion. The desired UI is shown below: https://i.sstatic.net/EFAlM.jpg Here is the HTML code I have developed so far: & ...

Parsing JSON sub items in Android application using Java

Here is a snippet of my PHP file: <?php $myObj = array( "name"=>"John" , "age"=>"30" , "post"=>[ "title"=>"What is WordPress" , "excerpt"=>"WordPress is a popular blogging platform" , ...

Is it possible to arrange two items in one column and the rest as columns in MaterialUI Grid?

I need help arranging my arrows in a MaterialUI grid where one points up and the other points down. How can I achieve this layout? Attached below is an image of my current setup and the desired outcome. Here is my code: <Paper className={classes.paper ...

having trouble retrieving 200 status code from Angular server response

Objective: I need to make certain changes to the record locally if the server responds with a 200 code. Problem: I am unable to retrieve the response code or access the 'message' attribute. This is the server response I receive from the HTTP ca ...

I'm noticing my table collapsing as I move around the div elements - any idea why this is happening

A challenge I am facing is creating a dynamic table where users can drag and drop colored boxes with animated transitions. While it mostly works well, sometimes the table collapses inexplicably. Here are steps to reproduce the issue: Move 100 - 400 Move 1 ...

How to display a div in Angular when hovering with ElementRef and Query List

I am having trouble implementing a ngFor loop in my project where I want to display a div on mouse hover using the @Input notation. This is how my HTML code looks: <div class="col s12 m6" style="position: relative" *ngFor="let res of hostInfo.resident ...

Strategically bypassing the third step to directly progress to the fourth step

Here's my code snippet in vue.js where I'm attempting to skip from the third step to the fourth step in a multi-step form. Essentially, if we're on the second step and press the next button, it should directly take us to the fourth step, byp ...

Hover over the first element to remove its class and replace it with a different element

I am attempting to develop a function that adds the class = "actived" to the first Element. This class has a CSS style that highlights the element in question. I have a list of 4 lines and I want the first one to automatically receive this class, while t ...

Tips for utilizing the Apollo cache consistently during page transitions in NextJs

In the official examples repository of NextJS, I found this apolloClient.js file: import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client' import { concatPagination } from '@apollo/client/utilities' import merge from &apos ...

Having trouble viewing the page of a new package you published on the NPM Website?

Today, I officially released an NPM package called jhp-serve. It can be easily installed using npm install or run with npx. You can even find it in the search results here: https://www.npmjs.com/search?q=jhp. However, when attempting to view its page by cl ...