В Angular v15 мы можем использовать новый API композиции директив, чтобы применять директивы непосредственно к элементу host
компонента. Создание пользовательских условных структурных директив на данный момент требует немного шаблонной работы. Давайте посмотрим, как мы можем использовать его для создания более чистых пользовательских директив ngIf
.
Предположим, что нам нужно переключить некоторые представления на основе проекта status
пользователя. Как хорошие разработчики, мы создадим повторно используемую директиву с именем ShowIfProjectActiveDirective
:
import { NgIf } from '@angular/common'; import { Directive, inject, Input } from '@angular/core'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; @UntilDestroy() @Directive({ selector: '[showIfProjectActive]', hostDirectives: [{ directive: NgIf, inputs: ['ngIfElse: showIfProjectActiveElse'] }, ], standalone: true, }) export class ShowIfProjectActiveDirective { @Input('showIfProjectActive') showIfProjectActive: boolean; private ngIfDirective = inject(NgIf); private projectService = inject(ProjectService); ngOnInit() { this.projectService.active$ .pipe(untilDestroyed(this)) .subscribe((isActive) => { this.ngIfDirective.ngIf = this.showIfProjectActive ? isActive : !isActive; }); } }
Функция hostDirectives
используется для создания экземпляра директивы NgIf
и применения ее к нашему элементу host
. Чтобы установить свойство ngIf
, мы получаем ссылку на экземпляр директивы NgIf
и устанавливаем его вручную на основе нашей логики active
.
Кроме того, мы хотим, чтобы потребители могли использовать встроенный ввод ngIfElse
, поэтому мы предоставляем ввод от NgIfDirective
под псевдонимом showIfProjectActiveElse
.
Теперь мы можем использовать нашу директиву в шаблоне:
<button *showIfProjectActive="true; else elseTpl">Foo</button> <ng-template #elseTpl>Bar</ng-template> <!-- Or use the ng-template version --> <ng-template [showIfProjectActive]="true" [showIfProjectActiveElse]="elseTpl"> Foo </ng-template>
Вот еще один пример представления на основе ролей:
import { NgIf } from '@angular/common'; import { Directive, inject, Input } from '@angular/core'; @Directive({ selector: '[ifHasRole]', hostDirectives: [{ directive: NgIf, inputs: ['ngIfElse: ifHasRoleElse'] }], standalone: true, }) export class IfHasRoleDirective { private ngIfDirective = inject(NgIf); private authorizationService = inject(AuthorizationService); @Input('ifHasRole') set role(role: 'admin' | 'user') { this.ngIfDirective.ngIf = this.authorizationService.hasRole(role) } }
И используйте его в шаблоне:
<button *ifHasRole="'admin'; else elseTpl">Foo</button> <ng-template #elseTpl>Bar</ng-template>
Подпишитесь на меня в Medium или Twitter, чтобы узнать больше об Angular и JS!