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

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly β€” using the tools and languages you already love!

Learn More

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).

πŸ‘‹ Kindness is contagious

Dive into this thoughtful article, cherished within the supportive DEV Community. Coders of every background are encouraged to share and grow our collective expertise.

A genuine "thank you" can brighten someone’s dayβ€”drop your appreciation in the comments below!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found value here? A quick thank you to the author makes a big difference.

Okay