2
votes

I've created two custom elements using Angular Elements.

<capp-customtag1> is defined in customtag1.js 
<capp-customtag2> is defined in customtag2.js.

I load <capp-customtag1> with <script type="text/javascript" src="assets/customtag1.js"></script>. 

Similarly, for <capp-customtag2>

Separately, they work as intended. However, if I try to use both of them in the same project (an Angular 6 project), when I attempt to load the second script, I get the following error:

ERROR DOMException: Failed to execute 'define' on 'CustomElementRegistry': this name has already been used with this registry.

The calls to CustomElementRegistry are made in customtag1.js and customtag2.js.

This is the code I use to create capp-customtag1 in the Angular Element AppModule constructor:

const el = createCustomElement(CustomTag1Component, {injector: this.injector});
customElements.define('capp-customtag1', el);

This is the code to create capp-customtag2 in the second project's AppModule constructor:

const el = createCustomElement(CustomTag2Component, {injector: this.injector});
customElements.define('capp-customtag2', el);

Why do both elements have the same custom element name? And, how can I fix the problem.

Thank you.

4
Could you post your .js files and your NgModule? - Bruno
As I understand, you are registering each custom element in each .js file, then you are including them in an Angular 6 project and then registering each customtag again in the NgModule. Is that correct? - Bruno
I am not registering the customtag again. I don't believe this is required. I simply use that customtag and load the js via a script tag. This works fine when only using one of the customtags. thanks. - RichardZ
I think your custom elements are not the problem. Check this issue someone else had with Polymer: github.com/Polymer/polymer/issues/5194 - Bruno
Seems like a similar issue. However, I'm not sure what that means as a solution for my problem? Independently created Angular Elements should coexist without a hack. - RichardZ

4 Answers

7
votes

As suspected, it's a bundling issue. The root cause is that webpack (which drives the CLI) uses a runtime: webpackJsonp global, and you're overwriting that each time you load another bundle (which also defines webpackJsonp) - See webpack/webpack#3791 (comment). The CLI doesn't expose this option (things like this are why angular are not supporting this use case yet). You could (though I don't recommend it) manually rename that global webpackJsonp in each bundle to something unique.

You're also duplicating all the polyfills, which is likely to cause all kinds of unexpected results, as they're shimming native APIs and overwriting them at various times. Further, bundling a copy of all the angular packages into each bundle seems suboptimal.

For the moment, if you want to do this sort of use case, your likely best option is going to be to use something like rollup to build UMD bundles, that rely on angular's UMD bundles and exclude the angular source from each element's package. It's going to take some manual work.

Alternately, don't use the CLI to build the individual elements into binaries, treat them as libraries and bring them into the build properly, so you only have one webpack runtime.

5
votes

I kept running into this error and I added a check to make sure the customElement was not already defined. Simply adding the following before defining the element should fix this error:

if (!customElements.get('webtest')) {  
    customElements.define('webtest', e3);
}
3
votes

I know this is quite late to answer but I faced the issue last night and these are my observations. Hope it helps others with this problem ahead.

The error is because of webpack conflict between the various angular applications on your page.

The solution is to change the jsonpFunction name in webpack.config.js of each of your web component applications.

Example:

module.exports = {
  //...
  output: {
    jsonpFunction: '<unique name for your application's json function>'
  }
};

Do this for both of your projects related to capp-customtag1 and capp-customtag1.

1
votes

I am facing similar kind of issue, what I have done is I put a hyphen in between the selector name.

my element selector name webtest to web-test

in app.module.js

before

const e3 = createCustomElement(WebelementTestComponent, { injector: this.injector });
customElements.define('webtest', e3);

after

const e3 = createCustomElement(WebelementTestComponent, { injector: this.injector });
customElements.define('web-test', e3);

then my problem has been solved.