Angular Elements

For creating custom elements, angular elements now support content projection using web standards.

Example

<my-custom-element>This content can be projected!</my-custom-element>

The support for the official Shadow DOM specification improved for Angular Elements. In Angular 7, content can also project into an Angular Element from the outside. This is done via the Native API using <slot> elements.

Angular Elements which are Angular components designed as web components that can be used alone now in Angular version 7 supports content projection using web standards for the custom HTML element

The introduction of the new standard HTML tag i.e <slot> is done by the Web Component Specification.

To perform content projection you can use ng-content, as shown in the listing below:

AppComponent.ts

import { Component } from '@angular/core';
@Component({
  selector: 'app-greet',
  template: `
 <h2>{{title}}</h2>
 <ng-content></ng-content>
`
})
export class AppComponent {
  title = 'Greet';
}

The problem faced with the above approach is that if you use AppComponent as an Angular Element then you will not be able to project content. To understand this in a better way, let us start by converting AppComponent to an Angular Element.

After converting AppComponent to an Angular Element, AppModule should look like the listing below:

AppComponent.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule
  ],
  exports: [
    BrowserAnimationsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(private injector: Injector) {
    const customElement = createCustomElement(AppComponent, { injector });
    customElements.define('app-root', customElement);
  }
  ngDoBootstrap() {
  }
}

Upon running application, you will find that <h2> element has not been projected to the Angular AppComponent.

Sahosoft Tutorials-Angular Element

After starting Angular 7

After releasing of Angular 7, another option available to perform content projection. For doing content projection in an Angular Element, you have to do following:

  • Set ViewEnacpsulation to ShadowDom.
  • Use slot instead of <ng-content>

Let us modify AppComponent as shown in the listing below:

AppComponent.ts

import { Component, ViewEncapsulation } from '@angular/core';
@Component({
  selector: 'app-greet',
  template: `
 <h2>{{title}}</h2>
 <slot name='message'></slot>
`,
  encapsulation: ViewEncapsulation.ShadowDom
})
export class AppComponent {
  title = 'Greet Component';
}

We have set the encapsulation to ShadowDom and replaced <ng-content> with <slot>

Angular has been supporting ShadowDom since its beginning. Until Angular 6.0, there were three-encapsulation modes:

  • Emulated
  • Native
  • None

The Native mode was used to create ShadowDom V.0 and emulated was the default mode. Starting with Angular 6.1, Angular started supporting ShadowDom V.1, also. The fourth option for the ShadowDom can be enabled by using ShadowDom V.1 on components. Angular creates Shadow Dom V.1 if you set encapsulation to ShadowDom.You must have encapsulation set to ShadowDom for doing content projection in an Angular Element.

Now, upon running the application, you will find the content has been projected as shown in the image below:

Sahosoft Tutorials-Angular Element

Therefore, you can project content in Angular Element in Angular 7.0 by using ShadowDom Encapsulation mode and slot.