DEV Community

Suguru Inatomi
Suguru Inatomi

Posted on • Originally published at blog.lacolaco.net on

2 1

Angular Elements: Composable Definition Pattern

Assuming a situation we have…

  • An Angular component library project, Lib1Module
  • An Angular Elements library project, Lib1ElementsModule
  • An Angular Elements library project, Lib2ElementsModule which uses Lib1ElementsModule

It can be achieved with loading scripts of both Lib1 and Lib2 separately. But composing multiple Angular Elements definition brings some benefits.

  • Unified Angular bootstrapping (better performance)
  • Single <script> tag in HTML (free from loading order problem)

Creating Lib1ElementsModule

import { createCustomElement } from '@angular/elements';

export function defineCustomElements(injector: Injector) {
  customElements.define(
    'lib1-button-element',
    createCustomElement(Lib1ButtonComponent, { injector })
  );
}

@NgModule({
  imports: [Lib1Module],
  // `entryComponents` is not needed if Ivy is enabled
  entryComponents: [Lib1ButtonComponent],
})
export class Lib1ElementsModule {
  constructor(private readonly injector: Injector) {}

  ngDoBootstrap() {
    defineCustomElements(this.injector);
  }
}

Enter fullscreen mode Exit fullscreen mode

To use Lib1ElementsModule , bootstrap it directly. Then ngDoBootstrap() method will be called.

// main.elements.ts
platformBrowserDynamic().bootstrapModule(Lib1ElementsModule);

Enter fullscreen mode Exit fullscreen mode

Creating Lib2ElementsModule

Lib2ElementsModule enables both Lib1 and Lib2 Angular Elements by composition.

import { createCustomElement } from '@angular/elements';
import {
  Lib1ElementsModule,
  defineCustomElements as defineLib1Elements,
} from 'lib1';

export function defineCustomElements(injector: Injector) {
  customElements.define(
    'lib2-card-element',
    createCustomElement(Lib2CardComponent, { injector })
  );
}

@NgModule({
  imports: [Lib2Module, Lib1ElementsModule],
  // `entryComponents` is not needed if Ivy is enabled
  entryComponents: [Lib2CardComponent],
})
export class Lib2ElementsModule {
  constructor(private readonly injector: Injector) {}

  ngDoBootstrap() {
    // Compose definition
    defineLib1Elements(this.injector);
    defineCustomElements(this.injector);
  }
}

Enter fullscreen mode Exit fullscreen mode

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay