О маленькой полезной фиче angular

от автора

Недавно появилась задача в одном достаточно крупном проекте ограничивать UI и функционал пользователей, в зависимости от их ролей. К этому моменту приложение уже разрослось на 100+ компонент, и это при том что основные базовые компоненты вынесены в отдельную репу и ставятся пакетом. То есть примерно в каждом из 100+, вероятно придется вносить некоторые правки, связанные с правами доступа.

Первой мыслью было пройтись по всем компонентам, заинжектить через DI UserService, прокинуть в шаблон контекст пользователя, и там с этим как-то разбираться. Однако, на счастье, я не успел этим заняться, так как нашел другое, как мне кажется более удачное решение.

exportAs

Я подумал о том, как можно сразу в шаблонах получить userContext, без необходимости инжектировать сервис или токен с пользователем в контроллерах компонент. На счастье вспомнилась весьма удобная штучка: свойство директив (ну и компонент, как наследников, естественно) — exportAs.

Что же дает exportAs?

Вот что нам сообщает документация:

exportAs: Определяет имя, которое может быть использовано в шаблоне для назначения этой директивы переменной.

Как же этим воспользоваться?

Допустим, у нас есть сервис, который авторизовался и хранит данные о пользователе.

@Injectable({   providedIn: 'root', }) export class UserService {   private user$: User;    set user(user: User) {     this.user$ = user;   }    get user() {     return this.user$;   }    constructor(     private _http: HttpClientWrapperService   ) {   }      ... }

И есть класс, описывающий пользователя

export class User {   id: number;   name: string;   claims: Claim[];    get roles() {     return this.claims?.map(_ => _.code);   }    get isAdmin() {     return this.roles?.indexOf('ADMIN') >= 0;   }    get isUser() {     return this.isAdmin || this.roles?.indexOf('USER') >= 0;   }    get isGuest() {     return this.isAdmin || this.isUser || this.roles?.indexOf('GUEST') >= 0;   }   ... }

Что нам нужно — создать директиву, которая будет иметь доступ к пользователю, например такую:

import {Directive} from '@angular/core'; import {UserService} from '../../service/user.service';  @Directive({   selector: '[appUserContext]',   exportAs: 'userContext' }) export class UserContextDirective {   get user() {     return this._user?.user;   }    constructor(private _user: UserService) {   } } 

И использовать ее по надобности в шаблонах приложения. Например так, если добавлять у удалять объект может только администратор.

<div class="column content-block" appUserContext #user="userContext"> <app-toolbar> <ng-container *ngIf="user.user?.isAdmin"> <button app-button (click)="add()"> <app-icon [name]="'add'"></teta-icon> </button> <button app-button (click)="delete()"> <teta-icon [name]="'delete'"></teta-icon> </button> </ng-container> </app-toolbar> </div>

Также данная функция может использована для получения доступа к директивам и компонентам в шаблоне, без необходимости использовать ViewChild там, где для этого нет большой необходимости.

Спасибо за внимание, надеюсь эта информация окажется для вас полезной и сэкономит кому-то время.


ссылка на оригинал статьи https://habr.com/ru/post/661213/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *