Как в Angular рендерить один компонент в другом по имени класса через сервис?

В Angular есть несколько способов рендерить один компонент в другом. Один из подходов состоит в использовании сервиса вместе с динамическим созданием компонентов.

Прежде всего, нужно создать сервис, который будет отвечать за динамическое создание компонентов. Для этого можно использовать ComponentFactoryResolver. Создадим новый файл, назовем его component-factory.service.ts:

import { Injectable, ComponentFactoryResolver, ViewContainerRef } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ComponentFactoryService {

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

  renderComponent(component: any, container: ViewContainerRef): void {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
    container.clear();
    container.createComponent(componentFactory);
  }
}

Этот сервис будет принимать компонент и контейнер, в который нужно вставить компонент, и будет создавать и рендерить компонент динамически.

Теперь давайте рассмотрим, как можно использовать этот сервис в другом компоненте. Создадим новый файл, назовем его parent.component.ts:

import { Component, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
import { ChildComponent } from 'path/to/child.component';  // Путь к дочернему компоненту
import { ComponentFactoryService } from 'path/to/component-factory.service';  // Путь к сервису

@Component({
  templateUrl: 'path/to/parent.component.html',  // Путь к HTML-шаблону
  styleUrls: ['path/to/parent.component.css']  // Путь к CSS-стилям
})
export class ParentComponent implements OnInit {

  @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;
  // Обратите внимание на `@ViewChild`, мы будем использовать его для получения ссылки на контейнер

  constructor(private componentFactoryService: ComponentFactoryService) { }

  ngOnInit(): void {
    this.renderChildComponent();
  }

  renderChildComponent(): void {
    this.componentFactoryService.renderComponent(ChildComponent, this.container);
  }
}

В этом примере мы используем ViewChild для получения ссылки на контейнер, в который мы будем вставлять компонент. Затем мы вызываем метод renderComponent сервиса ComponentFactoryService и передаем ему класс дочернего компонента ChildComponent и контейнер this.container.

Наконец, создадим HTML-шаблон для родительского компонента parent.component.html:

<div #container></div>

В этом шаблоне мы используем #container для определения места, в которое будет вставлен дочерний компонент.

Теперь, когда мы вызываем метод renderChildComponent в методе ngOnInit родительского компонента, дочерний компонент ChildComponent будет динамически создан и добавлен в контейнер container.

Это основной подход к рендерингу одного компонента в другом по имени класса через сервис в Angular.