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

[fix] Svelte for Web Components DOMException: Failed to execute 'define' on 'CustomElementRegistry': this name has already been used with this registry #7353

Closed
wants to merge 2 commits into from

Conversation

wyysf123
Copy link

@wyysf123 wyysf123 commented Mar 9, 2022

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • [ x ] Prefix your PR title with [feat], [fix], [chore], or [docs].
  • [ x ] This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with npm test and lint the project with npm run lint

wyysf123 added 2 commits March 9, 2022 19:51
When using svelte to create webcomponents components, I found a problem. For example, I created an Icon component first, and then used it for both the Dialog component and the Button component. At this time, an error will be reported saying that the Icon component has been repeatedly defined. To find the cause of the error in the source code of svelte, just modify this code to: ""if (component.tag ! = null) {
body.push(b !@_customElements.get("${component.tag}") && @_customElements.define("${component.tag}", ${name}););
fixed customElements.define error
@malindsay
Copy link

I've been pushing the use of Svelte for future javascript components, mainly web components. However, this issue is preventing that from occurring. Why can this simple change not make it into the build?

@baseballyama
Copy link
Member

Thank you for the PR!
But as I said below comment, I think this is not the proper way.

#7595 (comment)

@malindsay
Copy link

@baseballyama This still does not answer my concern. If I am going to start using Svelte in a large project that is loading web components dynamically, then I need to know a way to fix this issue. It appears fix needs to be in svelte, since the only hook to state a component is a WC is via
<svelte:options tag="element-tag-here" />

The rest is complied into Javascript. If this proposed PR is not the correct way, then how else to solve?

@baseballyama
Copy link
Member

the docs said...

Alternatively, use tag={null} to indicate that the consumer of the custom element should name it.

https://svelte.dev/docs#run-time-custom-element-api

Could you please tell us why the above way is not your solution?
In any case, hiding the error may render unexpected Custom Elements, so we need to tell it to a user at least.

@malindsay
Copy link

@baseballyama That is all and good but I am loading the pre compiled web component’s javascript file, so what would I use as the function (2nd parameter) to thre customElements.define.

I will say that no other frameworks such as angular or react requires the consumer to control registering.

@malindsay
Copy link

As I said before, using Svelte as my go to javascript ‘library’ is useless without this!
I work for a very large company which has a very large and out dated UI platform built with Angular. I am proposing and building a new means for external teams and applications to be loaded dynamically into a core UI built with Svelte. Everything will be dynamically loaded at runtime via using web components. I can achieve this using Svelte as base and loading any other web component built using angular, react, Stencil, etc. However, i have this problem with loading Svelte based web components in my Svelte base UI. As mentioned in previous comment, the define function expects a constructor. Show me an example of this, when all you have is the pre complied javascript file of a Svelte based web component.

@baseballyama
Copy link
Member

We can implement a register function like this.
Then, if a user wants to register all custom elements as regular names, then just they need to call defineCustomElements().
If a user wants to rename some of custom elements, then the user can set a name like defineCustomElements({ MyElement: "our-element" });.

so what would I use as the function (2nd parameter) to thre customElements.define.

I'm not sure about this question.
Compiled Svelte code will be a class, so just we can pass the class to the 2nd parameter right?

import MyElement from './MyElement.svelte';
import SomeElement from "./SomeElement.svelte";

const elements = { MyElement, 'my-special': SomeElement };

const toKebabCase = (tagName: string) => {
  return tagName
    .split(/(?=[A-Z])/)
    .join("-")
    .toLowerCase();
};

export const defineCustomElements = (customElementNames?: Record<keyof typeof elements, string>) => {
  Object.keys(elements).forEach((element) => {
    // I don't recommend to use try/catch here, but you can ignore the error without this PR.
    try {
      customElements.define(
        customElementNames?.[element] || toKebabCase(element),
        elements[element]
      );
    } catch (e) {
      console.error(e);
    }
  });
};

@baseballyama
Copy link
Member

Anyway, I think this PR is not right fix, so I close this now.
But thank you for your contribution @wyysf123

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants