Использование функции createComponent() в Angular
Angular v14.1 добавил новую функцию createComponent
. Эта функция может заменить заменяет ComponentFactory
, который использовался в предыдущих версиях. Функция позволяет создавать экземпляр ComponentRef
на основе предоставленного компонента и набора параметров:
import { ApplicationRef, createComponent, EnvironmentInjector } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class ToastService { constructor( private appRef: ApplicationRef, private injector: EnvironmentInjector ) { } open(text: string) { // Create a `ComponentRef` instance. const dialogRef = createComponent(ToastComponent, { environmentInjector: this.injector }); dialogRef.setInput('text', text); document.body.appendChild(dialogRef.location.nativeElement); // Register the newly created ref using the `ApplicationRef` instance // to include the component view into change detection cycles. this.appRef.attachView(dialogRef.hostView); } }
Можно передать новый environment injector, унаследованный от текущего:
export class ToastService { constructor( private appRef: ApplicationRef, private injector: EnvironmentInjector ) { } open(text: string) { const newEnvInjector = createEnvironmentInjector([ { provide: 'MyToken', useValue: 'Token' } ], this.injector); const dialogRef = createComponent(ToastComponent, { environmentInjector: newEnvInjector }); dialogRef.setInput('text', text); document.body.appendChild(dialogRef.location.nativeElement); this.appRef.attachView(dialogRef.hostView); } }
Так же можно создать element injector:
export class ToastService { constructor( private appRef: ApplicationRef, private injector: EnvironmentInjector ) { } open(text: string) { const elementInjector = Injector.create({ providers: [ { provide: 'MyToken', useValue: 'Token' } ], }); const dialogRef = createComponent(ToastComponent, { environmentInjector: this.injector, elementInjector }); dialogRef.setInput('text', text); document.body.appendChild(dialogRef.location.nativeElement); this.appRef.attachView(dialogRef.hostView); } }
Компонент может быть добавлен к элементу-хосту:
export class ToastService { constructor( private appRef: ApplicationRef, private injector: EnvironmentInjector ) { } open(text: string) { const dialogRef = createComponent(ToastComponent, { environmentInjector: this.injector, hostElement: document.getElementById('toasts-container')! }); dialogRef.setInput('text', text); this.appRef.attachView(dialogRef.hostView); } }
Мы можем передать projectableNodes
— список узлов DOM, которые должны быть проецированы через <ng-content>
нового экземпляра компонента:
openDialog<T>(dialogContent: Type<T>) { const footer = document.createElement('p'); footer.innerText = 'footer'; const dialogContentRef = createComponent(dialogContent, { environmentInjector: this.injector }) const dialogRef = createComponent(DialogComponent, { environmentInjector: this.injector, hostElement: document.getElementById('dialog-container')!, projectableNodes: [ // ng-content nodes [dialogContentRef.location.nativeElement], // second ng-content (e.g <ng-content select="footer"></ng-content>) [ footer ] ] }) this.appRef.attachView(dialogRef.hostView) }
Метод createComponent
в Angular используется для динамического создания экземпляров компонентов во время выполнения приложения. Это полезно, например, для создания модальных окон, динамической загрузки данных или интеграции с библиотеками сторонних разработчиков.