В этой статье показано, как использовать структурные директивы в Angular для предоставления простого декларативного механизма условного отображения контента.
Предположим, у нас есть проект с ролями «АДМИН», «РАЗРАБОТЧИК», «ПОЛЬЗОВАТЕЛЬ», и мы хотим скрыть части представления для определенных ролей.
Изначально нам нужно было
- В каждом представлении добавьте директивы *ngIf с проверкой роли пользователя
- Внедрить сервис в компонент, чтобы предоставить роль пользователя
- Предоставление компонента общедоступной собственности для отображения роли
Но это скучная копипаста… мы можем сделать это более причудливым способом, используя структурные директивы:
<div *visibleFor="['ADMIN', 'DEV']"> Visible for admin and dev </div> <div *visibleFor="'USER'"> Visible for user </div>
Гораздо проще читать и декларативнее, верно? Итак, давайте реализуем директиву visibleFor
@Directive({ selector: '[visibleFor]' }) export class VisibleForDirective implements OnDestroy, OnInit { private hasView: boolean = false; private user$: Observable<User>; private subscription: Subscription = new Subscription(); @Input() public set visibleFor(inputRoles: RoleString | Array<RoleString>) { const roles = isArray(inputRoles) ? inputRoles : [inputRoles]; this.subscription.unsubscribe(); this.subscription = this.user$.pipe(untilDestroyed(this)) .subscribe((user?: User) => { const hasAccess = user ? includes(roles, user.role) : false; if (hasAccess && !this.hasView) { this.viewContainer.createEmbeddedView(this.templateRef); this.hasView = true; } else if (!hasAccess && this.hasView) { this.viewContainer.clear(); this.hasView = false; } this.changeDetector.markForCheck(); }); } constructor( private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef, private changeDetector: ChangeDetectorRef, private userService: UserService) {} public ngOnInit(): void { this.user$ = this.userService.getUserRoles(); } public ngOnDestroy(): void {} }
Сам код говорит сам за себя. Он принимает оба массива строки. Он также использует сеттер для @Input(), поэтому каждый раз, когда ввод изменяется, вызывается весь сеттер.
Здесь используется замечательный оператор untilDestroyed https://github.com/NetanelBasal/ngx-take-until-destroy.
UserService — ваш поставщик данных, а RoleString — ваша строка для определения ролей пользователей:
type RoleString = ‘ADMIN’ | ‘DEV’ | ‘USER’;
Если вы хотите видеть больше похожего контента, пожалуйста, дайте мне знать, похлопав в ладоши.