Issue #4576Opened September 12, 2022by benryanwilliams1 reactions

BUG: Clicking 'wrap for style' button affects the inner components of other components inside the same text box

Question

GrapesJS version

  • I confirm to use the latest version of GrapesJS

What browser are you using?

Chrome 104.0.5112.101

Reproducible demo link

https://jsfiddle.net/7cLr0xt2/3/

Describe the bug

How to reproduce the bug? For some reason I'm unable to reproduce the bug inside the fiddle linked above, since line 34 selectedComponent.components('<span liquid="if contact.id">jhbjhhgjjh</span> <span liquid="else">qwewqeqwe</span>') doesn't replace the inner components of the component, so I'll have to share a video of what happens with my project instead, but the steps are as follows:

  1. Double click on the Hello World!!! text box and select the word 'World'
  2. Click on the paintbrush button in the RTE editor to wrap that word for styling
  3. Click the circled 'if' button on the far left of the component toolbar and click 'ok' on the dialog that pops up to convert this to a 'conditional-text' component
  4. Double click on the newly created Open conditionals to choose component (normally this would bring up a dialog but I've simplified for the sake of this bug, so now it just applies some dummy information to the component, including adding an attribute and changing the inner components of the component. Changing the inner components doesn't work in this fiddle though, not sure why)
  5. Click the 'view code' button to see the changes that this has made to the code - as you can see it has inserted the attribute liquidtag="if", but the inner components do not appear. In my project, the inner components of this span would be <span liquid="if contact.id">jhbjhhgjjh</span> <span liquid="else">qwewqeqwe</span>
  6. Close the 'view code' dialog and double click the word Hello to select it
  7. Click the paintbrush button in the RTE editor to wrap that word for styling
  8. Click the 'view code' button again - in my project, the inner components ( i.e. <span liquid="if contact.id">jhbjhhgjjh</span> <span liquid="else">qwewqeqwe</span>) of the first component that we created in step (4) now disappear (the attributes remain though)

What is the expected behavior? Wrapping a word for styling shouldn't change the inner components of other components in that div. Presumably this is because of the way that 'wrap for style' works - perhaps it sets the inner HTML of that component to the same as the inner HTML of the component's view?

What is the current behavior? The inner components <span liquid="if contact.id">jhbjhhgjjh</span> <span liquid="else">qwewqeqwe</span> set in step 5 disappear and are replaced with the 'displayedText' property when another word in the original text box is wrapped for styling. I'm thinking it could be something to do with lines 85 - 87 in the fiddle, but as far as I understand this should only affect the view and therefore how it appears inside the canvas, not the underlying HTML of the component.

Here is a video showing what happens in my project:

https://user-images.githubusercontent.com/67364267/189606601-2f7b280e-8436-459f-8951-c55337123216.mov

Code of Conduct

  • I agree to follow this project's Code of Conduct

Answers (3)

artfSeptember 13, 20221 reactions

RTE relies on the DOM content during the editing so if you remove it deliberately with something like

onRender() {
  this.el.innerHTML = this.model.get("displayedText")
},

inner components will be removed once the editing is finished.

benryanwilliamsSeptember 13, 20220 reactions

Ok thanks @artf, that makes sense.

However, those lines of code, along with

init() {
        this.listenTo(this.model, "change:displayedText", this.render)
      },

are required to render the correct selected state inside the canvas as follows (both upon the component initially being rendered and when the user selects a different 'if' state, thus changing displayedText):

https://user-images.githubusercontent.com/67364267/189854125-9544d34b-2f71-4b0c-872e-dbdfb2232fd9.mov

Can you think of a way to retain the inner components after editing via RTE? Perhaps I could store these inner components inside a property of the conditional-text component itself and assign these during onRender() also? If that's possible, how can I set the component's components property within the onRender() hook?

Thanks for your help!

benryanwilliamsSeptember 13, 20220 reactions

I need to do some more testing but it looks like I've got around this behaviour by saving the inner components inside the component itself when first creating it / editing it, then using the rte:disable hook as follows:

editor.on('rte:disable', () => { 
          const conditionalComponents = (editor.getSelected().components().filter((component) => {
            return component.attributes.type == 'conditional-text'
          }))

          conditionalComponents.forEach((component) => {
            component.components(component.attributes.conditionCode)
          })
});

It seems a bit hacky so if you can think of a better way then please let me know.

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.