Issue #3289Opened February 23, 2021by bgrand-ch2 reactions

BUG: (0.16.41) Components have lost their styles

Question

Version: 0.16.41

Are you able to reproduce the bug from the demo?

[X] Yes [ ] No

What is the expected behavior?

  1. Copy selected parent component (container) to the clipboard.
  2. Paste selected parent component (container) from the clipboard (into the same page or an other page).
  3. All components keep ID styles and inline styles.

What is the current behavior?

  1. Copy selected parent component (container) to the clipboard.
  2. Paste selected parent component (container) from the clipboard (into the same page or an other page).
  3. Components have lost their ID styles, but not their inline styles.

Components don't have a regenerated style ID, but the same previous ID with a "-2" appended.

Are you able to attach screenshots, screencasts or a live demo?

[X] Yes (attach) [ ] No

https://jsfiddle.net/bgrand_ch/71yuz26p/33/

From the jsfiddle above, follow the next steps :

  1. Select one component.
  2. Copy this component with Ctrl/Cmd + C.
  3. Paste the copied component with Ctrl/Cmd + V.
  4. All defined style have lost, inline style have preserved.

Copy-paste plugin (with Quasar notifications system):

import { Notify } from 'quasar'

/**
 * Copy paste into same page and between pages
 * @see https://grapesjs.com/docs/modules/Plugins.html
 * @param {object} editor
 * @param {object} options
 * @returns {void}
 */
export default function (editor, options) {
  /**
   * Copy a component to clipboard
   * @see https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText
   * @returns {void}
   */
  editor.Commands.add('core:copy', async () => {
    let timeoutId = null

    try {
      timeoutId = showNotification({
        message: 'Élément en cours de copie...',
        type: 'info',
        timeout: 600
      })

      await navigator.clipboard.writeText(
        JSON.stringify(
          getSelectedParent()
        )
      )

      showNotification({
        message: 'Élément copié avec succès !',
        type: 'success'
      })
    } catch (error) {
      showNotification({
        message: 'Impossible de copier l\'élément.',
        error
      })
    } finally {
      clearTimeout(timeoutId)
    }
  })

  /**
   * Paste a component from clipboard
   * @see https://grapesjs.com/docs/api/editor.html
   * @see https://grapesjs.com/docs/api/component.html
   * @see https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText
   * @returns {void}
   */
  editor.Commands.add('core:paste', async () => {
    let timeoutId = null

    try {
      timeoutId = showNotification({
        message: 'Élément en cours de collage...',
        type: 'info',
        timeout: 600
      })

      const selectedParent = JSON.parse(
        await navigator.clipboard.readText()
      )

      editor.getWrapper().append(selectedParent, {
        at: getSelectedParent().index() + 1
      })

      showNotification({
        message: 'Élément collé avec succès !',
        type: 'success'
      })
    } catch (error) {
      showNotification({
        message: 'Impossible de coller l\'élément.',
        error
      })
    } finally {
      clearTimeout(timeoutId)
    }
  })

  /**
   * Retrieves the parent component
   * @see https://grapesjs.com/docs/api/editor.html
   * @see https://grapesjs.com/docs/api/component.html
   * @returns {object}
   */
  function getSelectedParent () {
    return editor
      .getSelected()
      .closest(options?.parentSelector || '#wrapper > div')
  }

  /**
   * Shows a notification to the user
   * @see https://quasar.dev/quasar-plugins/notify
   * @param {string} message
   * @param {string} [type]
   * @param {object} [error]
   * @param {number} [timeout]
   * @returns {number|void}
   */
  function showNotification ({
    message,
    type = 'error',
    error = {},
    timeout = 0
  } = {}) {
    const notifType = {
      info: { icon: 'info', color: 'blue' },
      success: { icon: 'check_circle', color: 'green' },
      error: { icon: 'error', color: 'red' }
    }
    const options = {
      message,
      color: notifType[type].color,
      icon: notifType[type].icon
    }

    if (error instanceof Error) {
      options.caption = `Pour l'IT : ${error?.message}`
    }

    const notify = () => Notify.create(options)

    if (timeout > 0) {
      return setTimeout(() => notify(), timeout)
    }

    notify()
  }
}

Answers (3)

artfMarch 4, 20211 reactions

That because you've updated original commands with your versions (incorrectly). Indeed, if I remove your plugin from the demo everything works as expected. Please check the original copy and paste command, you should clone components before paste, so, your implementation couldn't work.

bgrand-chMarch 4, 20210 reactions

@artf Thanks for your answer. A link or an example or more explanations please? 😅

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.