primocms / primo

Primo is a visual CMS with a built-in code editor, Svelte blocks, and static site generator.
https://primocms.org
MIT License
1.92k stars 474 forks source link

Explicitly set editable fields should be excluded from implicit editing #347

Open rallisf1 opened 10 months ago

rallisf1 commented 10 months ago

I have an accordion module with a somewhat complex structure:

<section class="page-container" id="faq">
  <h2 class="heading">{heading}</h2>
  <div class="accordion">
    {#each items as item, i (i)}
    <div class="item article" class:active={activeItem === i}>
      <button on:click={() => setActiveItem(i)}>
        <Icon icon="material-symbols:expand-{ activeItem === i ? 'less' : 'more'}" style="color:var(--primary);" height=32 />
        <h4 data-key="items[{i}].title">{item.title}</h4>
      </button>
      {#if activeItem === i}
      <article data-key="items[{i}].description" class="description" transition:slide>{@html item.description.html}</article>
      {/if} 
      <noscript>
        <article class="description">{@html item.description.html}</article>
      </noscript>
    </div>
    {/each}
  </div>
</section>

When clicking in the description it adds it to the title every time.

Edit: removed video, you can use the json provided to recreate.

rallisf1 commented 10 months ago

Here's the whole symbol

FAQ.json.zip

mateomorris commented 10 months ago

Yeah I've noticed that happening on Accordions but haven't filed a bug for it yet, will look into it

vortizhe commented 7 months ago

I'm suffering this too.

I discover make_content_editable() function on src/lib/views/editor/Layout/ComponentNode.svelte search the text to find which element is to add the data-key to bind the element with the data. Since the rest of the content is hidden, it fails to bind the correct element and bind to a parent.

In your case, check if this element <div class="item article" class:active={activeItem === i}> get the data-key for the title in the visual editor.

I have a workaround, editing ComponentNode.svelte and adding the possibility to avoid to make editable some elements with data-noeditable.

async function make_content_editable() {
    if (!node) return
    const valid_elements = Array.from(node.querySelectorAll('*')).filter((element) => {
        if (['STYLE', 'TITLE'].includes(element.tagName)) return false
        if (Object.keys(element.dataset).includes('noeditable')) return false;
        ....

Maybe @mateomorris can find a more elegant solution for this.