7

I try to get Angular Elements working in IE11. My custom element (simple button) is already displayed and the input binding is working as expected, but the output binding doesn't.

A click on my custom element button in IE 11 results in the error:

The object doesn't support this action

What I have done so far:

  1. Remove polyfill for custom elements that was added with ng add @angular/elements (didn't work properly with IE)
  2. Update all Angular packages to 7.2.1

  3. Add the following polyfillls to polyfills.ts:

import 'core-js/shim'
import '@webcomponents/shadydom/shadydom.min.js';
import '@webcomponents/custom-elements/src/native-shim';
import '@webcomponents/custom-elements/custom-elements.min';
  1. Bootstrap the module manually

  2. ng build --output-hashing=none and package all generated files into btn-element.js which is served with http-server for local testing (see index.html below).

Do I miss a specific polyfill or am I doing something wrong? Or is it just not possible yet?

app.module.ts:

@NgModule({
  declarations: [ ButtonComponent ],
  imports: [ BrowserModule ],
  entryComponents: [ ButtonComponent ]
})
export class AppModule {
  constructor(private injector: Injector) {
    const customBtn = createCustomElement(ButtonComponent, { injector });
    customElements.define('app-btn', customBtn);
  }
  ngDoBootstrap() { }
}

button.component.ts:

@Component({
  template: `<button (click)="handleClick()">{{ label }}</button>`,
  encapsulation: ViewEncapsulation.ShadowDom
})
export class ButtonComponent {
  @Input() label;
  @Output() myaction = new EventEmitter<number>();
  private clicksCt: number = 0;

  constructor() { }

  handleClick() {
    this.clicksCt++;
    this.myaction.emit(this.clicksCt);
  }
}

index.html

<html lang="en">
<head>  
  [...]
  <script type="text/javascript" src="btn-element.js"></script>
</head>
<body>
<app-btn label="Button Text"></app-btn>

<script>
    var button = document.querySelector('app-btn');
    button.addEventListener('myaction', function (event) {
         console.log('action emitted: ' + event.detail);          <!-- not working! -->
     });
     setTimeout(function () {
         button.label = 'Async value change happened...'   <!-- working! -->
     }, 2000);
    }
</script>
</body>
</html>

I also tried <app-btn label="Button Text" (myaction)="test($event)"></app-btn> without success.

Edit: Minimal Example

It seems not to be wokring in IE 11. To reproduce my reslut and see the same as if the StackBitz is run in Chrome, follow those steps:

  1. Copy to local machine
  2. run npm install
  3. run npm run build && npm run package:win (for Windows)
  4. serve the index.html and the generated btn-element.js with http-server
jowey
  • 7,581
  • 6
  • 27
  • 46
  • Can't reproduce your problem based on your polyfills.ts, it will show the module not found error (even I install the webcomponents). So, can you post the Enough code to reproduce the problem as in [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). Otherwise, I'm trying to create custom elements using @angular/elements, and will show you the result. – Zhi Lv Jan 23 '19 at 06:43
  • Besides, I suggest you could use F12 developer tools to check whether the btn-element.js file load success and whether it contains some js error. – Zhi Lv Jan 23 '19 at 08:11
  • Thank you for taking the time. I think by checking if I forgot to post a relevant piece of code, I found the error. Sadly as I wanted to repeat the steps made to verify it, I can't check it because IE is crashing all the time if I open the dev tools. So I would be really interested how you are creating CE if you also package them and they work in IE 11. – jowey Jan 23 '19 at 08:13
  • @ZhiLv-MSFT added a StackBitz anyway [example](https://stackblitz.com/edit/angular-qcx7ju). – jowey Jan 23 '19 at 09:47
  • @jowey did you figure this out? I have the same problem – lblu Jan 02 '20 at 23:56
  • @lblu I discontinued work on this for a while now, because for me it seems there isn't a solution for the problem. If I have time, I will investigate this again in the next months with Angular 9. If this will work, or the shims might have improved, I will report, but honestly I don't have much hope. – jowey Jan 03 '20 at 13:22

2 Answers2

0

From the official document we could see that:

The recently-developed custom elements Web Platform feature is currently supported natively in a number of browsers. Support is pending or planned in other browsers.

enter image description here

I also try to test the official document contain's demo, it works well in the Chrome browser, not working in IE/Edge browser.

In the IE browser it will show the syntax error, like this:

enter image description here

So, as the official document said, they are working on implementing custom element to support IE/Edge browser.

Community
  • 1
  • 1
Zhi Lv
  • 18,845
  • 1
  • 19
  • 30
  • Added a StackBitz for everyone interested, as it seems I got a little bit farther by setting TS target type to ES5 and adding some polyfills. My component displays and input bindings work, but as the title tells, the output binding does not. – jowey Jan 23 '19 at 09:51
  • And where in the docs do you find that they work on IE support? Native IE support isn't possible in fact, because IE needs ES5. – jowey Jan 23 '19 at 10:00
  • There are lots of polyfills for custom elements in older browser. Even one supported by Google (LitElement) so I'd be surprised if Angular doesn't support "Angular Elements" in older browsers. – moefinley Feb 27 '20 at 09:12
  • It does say in the docs that it should work for ES5 browsers https://angular.io/guide/elements#browser-support-for-custom-elements – moefinley Feb 27 '20 at 17:33
0

I have this working in a small project. Here is a check list of things that need to be in place.

To run Angular Elements in IE11 you need:

  • Compile your Angular application to ES5 and the production flag
  • Include the Polymer project webcomponentsjs/custom-elements-es5-adapter.js to get the ES5 syntax to work with the customElements API in modern browsers
  • Included the Polymer project web components polyfill webcomponentsjs/webcomponents-loader.js https://www.webcomponents.org/polyfills/
  • Make sure these are in the correct order alongside the Angular code
<script type="text/javascript" src="dist/AngularComponentTest/runtime.js"></script>
<script type="text/javascript" src="dist/AngularComponentTest/polyfills.js"></script>
<script src="webcomponentsjs/custom-elements-es5-adapter.js"></script>
<script src="webcomponentsjs/webcomponents-loader.js"></script>
<script type="text/javascript" src="dist/AngularComponentTest/main.js"></script></body>
  • To load a simple component you wont need any of the "Browser Polyfill" from polyfills.ts to be enabled
  • Do not include custom-elements-es5-adapter.js using anything that will mean it's transpiled e.g. Angular build config's scripts or polyfill.ts

Doing the above using Angular 9 gave me everything need to run an Angular Element and emit an event from it.

I will post a sample application when I have cleaned it up a bit.

moefinley
  • 1,248
  • 1
  • 13
  • 26