Failing to Consume Typescript Compiled ESNext customElements in Angular Project Via NPM

Failing to Consume Typescript Compiled ESNext customElements in Angular Project Via NPM

If you are working on an Angular project and trying to consume Typescript compiled ESNext customElements from an external library via NPM, you may encounter some issues. In this blog post, we will explore the problem and provide multiple solutions to help you overcome this challenge.

The Problem

When you try to consume Typescript compiled ESNext customElements in an Angular project via NPM, you may face the following error:

Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.

This error occurs because Angular uses its own zone.js library, which patches the global ‘HTMLElement’ constructor. As a result, the Typescript compiled ESNext customElements fail to construct properly.

Solution 1: Disable Zone.js Patching

The first solution to this problem is to disable the zone.js patching for the ‘HTMLElement’ constructor. This can be achieved by adding the following code snippet in your main.ts file:

// main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';

// Disable zone.js patching for HTMLElement constructor
(window as any).__Zone_disable_constructor = true;

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

By setting the ‘__Zone_disable_constructor’ property to ‘true’, we prevent zone.js from patching the ‘HTMLElement’ constructor. This allows the Typescript compiled ESNext customElements to construct properly.

Solution 2: Use Custom Element Schema

If disabling zone.js patching is not feasible for your project, another solution is to use a custom element schema in your Angular project. This schema will inform Angular that certain elements should not be treated as Angular components.

To use a custom element schema, follow these steps:

  1. Create a file named ‘custom-elements-schema.json’ in the root of your Angular project.
  2. Add the following code snippet to the ‘custom-elements-schema.json’ file:
{
  "$schema": "http://json-schema.org/draft-07/schema",
  "type": "object",
  "properties": {
    "schemas": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "tagName": {
            "type": "string"
          },
          "isComponent": {
            "type": "boolean",
            "const": false
          }
        },
        "required": ["tagName", "isComponent"]
      }
    }
  }
}
  1. In your ‘angular.json’ file, add the following code snippet to the ‘architect’ -> ‘build’ -> ‘options’ section:
"customElements": {
  "schemas": [
    "src/custom-elements-schema.json"
  ]
}

By adding the ‘customElements’ property to your ‘angular.json’ file, you inform Angular to use the custom element schema defined in the ‘custom-elements-schema.json’ file.

Conclusion

When trying to consume Typescript compiled ESNext customElements in an Angular project via NPM, the zone.js patching and Angular component treatment can cause issues. In this blog post, we explored two solutions to overcome this problem. You can either disable zone.js patching for the ‘HTMLElement’ constructor or use a custom element schema in your Angular project.

By implementing one of these solutions, you should be able to successfully consume Typescript compiled ESNext customElements in your Angular project via NPM.


Posted

in

,

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *