BuilderIO / builder

Visual Development for React, Vue, Svelte, Qwik, and more
https://builder.io
MIT License
7.58k stars 950 forks source link

@builder.io/sdk-vue: Editing fails for empty/unpublished content #3653

Open kerwanp opened 1 month ago

kerwanp commented 1 month ago

Describe the bug

When following the documentation on how to Add Symbol editing to your app it results in a blank page on the editor.

To Reproduce

Steps to reproduce the behavior:

  1. Create a new Nuxt application npx nuxi@latest init <my-app>
  2. Install and configure Builder
  3. Follow the Add Symbol editing to your app
  4. Edit a Symbol in the editor with the preview url targeting the /edit-symbol page (depend on the page you created)

Expected behavior

The Symbol should be shown on the editor preview.

Screenshots

Editor screenshot image

Iframe content image

Additional context

All Symbols that were tested are working properly on Next.js as we were thinking about migrating to Nuxt (and this is the only blocking point).

This as been tested with and without API key on the Content component.

When looking at the console, there is no error emitted by Builder package. And there is no requests made to builder domains.

kerwanp commented 1 month ago

After some digging, it seems there is an issue when enabling the editor. The initeditingbldr event is never triggered as elementRef is not defined. When calling the component method directly to listen to the window messages it starts displaying the content properly.

Work around example of the patch (mounted method of the EnableEditor component)

  mounted() {
    var e, t;
    if (I()) {
      // Calling manually the method works
      this.elementRef_onIniteditingbldr()

      // This will not dispatchEvent as elementRef is undefined
      if (R() && this.$refs.elementRef && this.$refs.elementRef.dispatchEvent(
        new CustomEvent("initeditingbldr")
      ), this.builderContextSignal.content && G(this.canTrack)) {
        const o = (e = this.builderContextSignal.content) == null ? void 0 : e.testVariationId, r = (t = this.builderContextSignal.content) == null ? void 0 : t.id, i = this.apiKey;
        ue({
          type: "impression",
          canTrack: true,
          contentId: r,
          apiKey: i,
          variationId: o !== r ? o : void 0
        });
      }
      Mt() && !R() && this.$refs.elementRef && this.$refs.elementRef.dispatchEvent(
        new CustomEvent("initpreviewingbldr")
      );
    }
  },

It seems that there are some issues with the core components but by overriding them with custom ones resolves the issues.

Example with a simple text:

Failed setting prop "attributes" on <div>: value [object Object] is invalid. TypeError: Cannot set property attributes of #<Element> which has only a getter
    at patchDOMProp (runtime-dom.esm-bundler.js:660:11)
    at patchProp (runtime-dom.esm-bundler.js:771:5)
    at mountElement (runtime-core.esm-bundler.js:4836:11)
    at processElement (runtime-core.esm-bundler.js:4783:7)
    at patch (runtime-core.esm-bundler.js:4651:11)
    at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js:5289:11)
    at ReactiveEffect.run (reactivity.esm-bundler.js:222:19)
    at setupRenderEffect (runtime-core.esm-bundler.js:5417:5)
    at mountComponent (runtime-core.esm-bundler.js:5192:7)
    at processComponent (runtime-core.esm-bundler.js:5145:9) 
kerwanp commented 1 month ago

After digging more in Builder.io source code, the generated EnableEditor component template is the following:

<template>
  <template v-if="builderContextSignal.content">
    <component
      ref="elementRef"
      :onClick="(event) => onClick(event)"
      :builder-content-id="builderContextSignal.content?.id"
      :builder-model="model"
      :className="getWrapperClassName(content?.testVariationId || content?.id)"
      :is="ContentWrapper"
      :onIniteditingbldr="(event) => elementRef_onIniteditingbldr(event)"
      :onInitpreviewingbldr="(event) => elementRef_onInitpreviewingbldr(event)"
      v-bind="{ ...{}, ...{}, ...showContentProps, ...contentWrapperProps }"
      ><slot
    /></component>
  </template>
</template>

As when previewing Symbols we do not pass any content, elementRef does not exist and the if statement for dispatching the initeditingbldr does not pass.

By giving a random defined value as content the event is emitted and the Symbol preview works:

<template>
  <Content
    model="symbol"
    :content="true"
  />
</template>
samijaber commented 3 weeks ago

@kerwanp Appreciate you creating an issue and a PR to fix it.

We actually have a better solution in mind: to render the ContentWrapper when in previewing/editing modes but hide it using CSS. We will work on implementing this soon.

this will allow us to keep the event listener approach, which is better for performance.