angular
April 12, 2024
Передача инжектора во вложенные шаблоны
Начиная с 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() теперь принимает инжектор как третий аргумент.