Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom element wrapped in HTMLElement duplicates component when using v-model #9885

Closed
jcbond92 opened this issue Dec 20, 2023 · 5 comments
Closed
Labels
has workaround A workaround has been found to avoid the problem scope: custom elements

Comments

@jcbond92
Copy link

jcbond92 commented Dec 20, 2023

Vue version

3.3.11

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-jeblju?file=src%2FApp.vue

Steps to reproduce

  • Open Stackblitz
  • Observe that my-input is double rendering when wrapped in a div while using v-model
    Screenshot 2023-12-20 at 3 31 24 PM

What is expected?

my-input should be able to use v-model when it is placed inside of an HTMLElement.

What is actually happening?

  • When my-input uses v-model the contents of the custom element's shadow root are duplicated. This only happens when it is wrapped in an HTMLElement like a div.
  • When my-input's parent is template this issue doesn't occur.
  • Additionally this only seems to impact custom elements that are created with defineCustomElement, that are then reused in Vue (components created with Lit for example, don't seem impacted).

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.10.5 - /usr/local/bin/pnpm
  npmPackages:
    vue: ^3.3.11 => 3.3.13 

Any additional comments?

I found this issue when working to get different v-model types working with custom elements, #9883.

@jcbond92
Copy link
Author

Looking into this some more, it seems like the issue is coming from the fact that the custom element here uses a value prop. If I change the prop name to something like nativeValue everything works as expected.

The other workaround I have right now is to remove the extra node when the component mounts.

@edison1105 edison1105 added the has workaround A workaround has been found to avoid the problem label Jan 4, 2024
@jcbond92
Copy link
Author

Working on getting a pull request up to fix this, and interestingly if put a small timeout around the initial setting of the value in vModel.ts I see the duplication issue resolved.

mounted(el, { value }) {
    setTimeout(() => {
      el.value = value == null ? '' : value
    }, 1)
  },

@jcbond92
Copy link
Author

jcbond92 commented Jul 11, 2024

Seems to be some sort of collision with the update process in apiCustomElement.ts as I'm looking a bit more, and I think we can fix the issue there.

@jcbond92
Copy link
Author

Ok, so I think I've settled on a better solution than making a change in the mentioned pull request. I think this can be handled on a case-by-case basis by library authors.

The solution, I came up with was to wait for nextTick when registering the component in the custom elements registry. So, if you have an entry point for your component that users are importing to register it, like input.js you can handle the issue there:

import { defineCustomElement, nextTick } from "vue";
import MyTextInput from "./Input.ce.vue";
export const TextInput = defineCustomElement(MyTextInput);

export default (function () {
  if (customElements.get("my-input") === undefined) {
      nextTick(() => {
        customElements.define("my-input", TextInput);
      });
  }
})();

There is probably something clever you could do here with checking to see if your custom element is rendering in a Vue app (rather than Angular or React, for example), as well.

@jcbond92
Copy link
Author

Actually, after some additional investigation, this doesn't seem to work when multiple instances of a component are used in a specific view. I'll reopen the #11335 with some fixes to get the tests passing.

@jcbond92 jcbond92 reopened this Jul 12, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Aug 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
has workaround A workaround has been found to avoid the problem scope: custom elements
Projects
None yet
3 participants