DEV Community

Krzysztof Platis
Krzysztof Platis

Posted on • Edited on

4

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.

If you really feel like buying me a coffee

... then feel free to do it. Many thanks! 🙌

Buy Me A Coffee

Retry later

Top comments (3)

Collapse
 
genyklemberg profile image
Yevheniy Potupa

looks like createComponent is not part of Angular docs.

Collapse
 
krisplatis profile image
Krzysztof Platis

Hi Yevheniy!
Did you try those links?

Collapse
 
genyklemberg profile image
Yevheniy Potupa

Yes, now I see. But looks like it breakes hydration logic for SSR project (we can see two same items simultaniously during hydration).

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Retry later