DEV Community

Krzysztof Platis
Krzysztof Platis

Posted on

How to create an Angular component with a different HTML tag than the selector 🏷

Usually the HTML tag of an Angular component is it's selector. But it's possible to create a component with a different host HTML element. If you want to create a component statically (in the HTML template), you can use an attribute selector defined in the @Component decorator. Or if you want to create a component dynamically via Angular API (e.g. createComponent() or ComponentFactory.create()), you can pass a custom host DOM element as a parameter.

Creating a component statically

TLDR: See the stackblitz: creating a component statically with a custom HTML tag.

Define a component with an attribute selector instead of element selector:

@Component({ 
  // Note the brakets around `my-component`, denoting an "attribute selector" instead of "element selector"
  selector: '[my-component]' 
  /* ... */
})
export class MyComponent { /* ... */ }
Enter fullscreen mode Exit fullscreen mode

Then create this component with a custom HTML tag, by referencing it as an attribute:

<article my-component></article>
Enter fullscreen mode Exit fullscreen mode

Creating a component dynamically

TLDR: See the stackblitz: creating a component dynamically with a custom HTML tag .

Here, the selector doesn't matter. Can be even normal:

@Component({ 
  selector: 'my-component' 
  /* ... */
})
export class MyComponent { /* ... */ }
Enter fullscreen mode Exit fullscreen mode

Then pass an existing DOM element as a host to the function for creating the component dynamically (e.g. to createComponent() from @angular/core):

import {
  createComponent,
  /* ... */
} from '@angular/core';

@Component(/*...*/)
export class ParentComponent {
  constructor(
    protected injector: Injector,
    protected environmentInjector: EnvironmentInjector,
    protected viewContainerRef: ViewContainerRef
  ) {}

  ngOnInit() {
    // create a fresh element, detached from DOM
    const hostElement = document.createElement('article');

    // create MyComponent, passing the `hostElement` param
    const component = createComponent(MyComponent, {
      hostElement, // <-----------------------------------
      environmentInjector: this.environmentInjector,
      elementInjector: this.injector,
    });

    // insert this component into the `ViewContainerRef` of the parent component
    this.viewContainerRef.insert(component.hostView);
  }
Enter fullscreen mode Exit fullscreen mode

Note: The function createComponent() was added only in Angular 14.2 (see CHANGELOG). The same feature is available also in ComponentFactory (which is deprecated at the moment of writing).

See a similar example usage with ComponentFactory:

constructor(
    protected injector: Injector,
    protected componentFactoryResolver: ComponentFactoryResolver,
    protected viewContainerRef: ViewContainerRef
  ) {}

  ngOnInit() {
    // create a fresh element, detached from DOM
    const hostElement = document.createElement('article');

    const componentFactory =
      this.componentFactoryResolver.resolveComponentFactory(MyComponent);
    // create MyComponent, passing the `hostElement` param
    const component = componentFactory.create(
      this.injector,
      undefined,
      hostElement // <-----------------------------------
    );
    this.viewContainerRef.insert(component.hostView);
  }
Enter fullscreen mode Exit fullscreen mode

Here you can find also the working example on stackblitz using ComponentFactory.

Top comments (0)