0

I've been testing out Angular Elements. Basically I created 2 angular elements: a simple button and a simple input. You can check them out here: http://kaloyanmanev.com/edo-button.js and http://kaloyanmanev.com/edo-input.js

Both of the elements include their own polyfills, main, runtime, scripts, and styles concatenated as shown here: https://blog.angulartraining.com/tutorial-how-to-create-custom-angular-elements-55aea29d80c5

I am trying to include those in a HTML file like this:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <edo-button></edo-button>
  <edo-input></edo-input>
  <edo-button></edo-button>
</body>
<script src="http://kaloyanmanev.com/edo-button.js"></script>
<script src="http://kaloyanmanev.com/edo-input.js"></script>
</html>

Basically what happens is that I get 2 buttons but no input between them and of course that nasty error:

Error: Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.
The most likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise API is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)

When I use the scripts separately it works... If I include them both it doesn't. I researched a bit but couldn't find any solution. Seriously there is no way using 2 angular elements in one page?

Most likely the issue is caused by zone.js that Angular uses. I tried removing it from the polyfills of the elements but then I got an error that zone.js is required and none of the elements worked.

So how to use those elements?

*EDIT

I remove the polyfills from the bundle and I am including zone.js from a CDN. Still, there is another error going on:

ERROR DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "`edo-button`" has already been used with this registry
Yashwardhan Pauranik
  • 5,370
  • 5
  • 42
  • 65
Kaloyan Manev
  • 406
  • 6
  • 20

3 Answers3

0

You should create one project for the two-component.

Both of them are using zone.js and overwriting the original browser promise. That's why you got the error.

There are two options.

  1. You can add both of the components to the same module. This will cause a little bit of bigger js files (if common things do not count) instead of adding only the needed js files. E. g. if the site has the only button you won't need the extra for the input.

  2. On the other hand, you can create js files like edo-button, edo-input, edo-button-and-input. I don't think that 1 or 2 kB matter that much.

Yashwardhan Pauranik
  • 5,370
  • 5
  • 42
  • 65
androbin
  • 1,622
  • 14
  • 31
  • I don't want to make another angular project for those files. – Kaloyan Manev Nov 14 '19 at 23:14
  • I edited the answer. You don't need to make more project. One project is enough for both of the components. Into the `app.module.ts` add both of the components you want to use as elements. One JS file is enough as the 1st option in the answer. – androbin Nov 14 '19 at 23:30
  • But I want to be able to use them as 2 separate components. – Kaloyan Manev Nov 14 '19 at 23:38
  • Then the second is the go for you. It takes more time to do. I don't think the other component that you don't use will ruin anyhow the performance of your application. – androbin Nov 14 '19 at 23:40
0

Updating zone.js in package.json to 0.10.3 resolved this issue. ["zone.js": "0.10.3"]

Reference: https://github.com/angular/angular/issues/11650

Ashutosh Shukla
  • 557
  • 5
  • 9
  • This worked for me as well. Was previously using 0.9.3 with angular 8 for my webapp and a seperate web component bundle. – Peter Drinnan Aug 25 '20 at 04:09
-2

The problem you are facing is because Zone.js is getting loaded multiple times and hence overwriting the promise.

The solution to this problem lies in the build process of your web components.basically you need to separate out your library files and your web component logic and load them separately.

ng add ngx-build-plus

Post adding ngx-build-plus you need to make some changes in your app.module.ts file

import { BrowserModule } from '@angular/platform-browser';
import {DoBootstrap, Injector, NgModule} from '@angular/core';

import { AppComponent } from './app.component';
import {createCustomElement} from '@angular/elements';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  // bootstrap: [AppComponent],
  entryComponents: [
    AppComponent
  ]
})
export class AppModule implements DoBootstrap {
  constructor(private injector: Injector) {

  }

  ngDoBootstrap() {
    const el = createCustomElement(AppComponent, { injector: this.injector });
    customElements.define('phoenix-wc-wiki-ngx', el);
  }
}

Run following command

ng build --prod --output-hashing none --single-bundle true

Now you can find the separated files in the dist folder which you can use in your application. All you need to do is include zone.js only once and your components will load as the should.

Yashwardhan Pauranik
  • 5,370
  • 5
  • 42
  • 65
Nilesh Mahajan
  • 3,506
  • 21
  • 34