angular
April 12
Передача инжектора во вложенные шаблоны
Начиная с Angular 14 инжектор можно передавать для при использовании вложенных шаблонов. В прошлом это было возможно только с помощью директивы ngComponentOutlet
или API createComponent
.
Давайте посмотрим, как это можно сделать:
Передача контекста
Когда шаблон передаётся компоненту, контекст инжектора для него и его дочерних элементов исходит из места объявления шаблона, а не из того места, где он был создан. Это поведение при необходимости можно изменить.
<app-foo [tpl]="tpl"></app-foo> <ng-template #tpl> <app-bar></app-bar> </ng-template>
@Component({ selector: 'app-bar', template: `{{ name }}` }) export class BarComponent { constructor(@Inject('name') public name: string) {} }
@Component({ selector: 'app-foo', template: ` <ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletInjector]="injector"> </ng-template> ` providers: [{ provide: 'name', 'User' }] }) export class FooComponent { @Input() tpl: TemplateRef<any>; constructor(public injector: Injector) { } }
Создаётся новый провайдер в инжекторе компонента и передаётся инжектор ngTemplateOutletInjector
. Теперь BarComponent
будет использовать name
, из инжектора FooComponent
.
Обратите внимание, что новый инжектор действует как узловой инжектор, а не как инжектор модуля.
ViewContainer
<ng-container *appBaz> <app-bar></app-bar> </ng-container>
@Component({ selector: 'app-bar', template: `{{ name }}` }) export class BarComponent { constructor(@Inject('🎁') public name: string) { } }
@Directive({ selector: '[appBaz]' }) export class BazDirective { constructor(private vcr: ViewContainerRef, private tpl: TemplateRef<any>) { } ngOnInit() { this.vcr.createEmbeddedView(this.tpl, {}, { injector: Injector.create({ providers: [{ provide: '🎁', useValue: '😝' }] }) }) } }
Метод createEmbeddedView()
теперь принимает инжектор как третий аргумент.