Real Life Case – Dyrektywa do obsługi ról

Hej! Czas wrócić do aktywności z nowymi wpisami – będzie więcej krótkich artykułów z przypadkami, które uznałem za interesujące lub sprytne podczas pracy z angularowymi aplikacjami. Dzisiaj pokażę, jak radzę sobie z warunkowym wyświetlaniem elementów na podstawie ról użytkownika. Zaprezentuję rozwiązanie, którego prekursorem był kolega z teamu –  Tomasz Borowski z https://angular-in-space.pl, a które stosuję do dzisiaj z wielką przyjemnością.

*hasRoleDirective

Naszym celem jest napisanie dyrektywy strukturalnej, którą będziemy mogli używać w następujący sposób w templatce:

Przekazujemy w tablicy określone role – a dyrektywa weryfikuje czy profil zalogowanego użytkownika posiada jedną z nich. Brzmi prosto. A kod…jest jeszcze prostszy! Jestem przekonany, że wyświetlałeś/aś elementy warunkowo już wiele razy przy użyciu dyrektywy *ngIf, prawda? Więc po co wynajdywać koło od nowa? Rozszerzmy ją i dodajmy co trzeba.

Sprytnie wykorzystujemy dziedziczenie i nadpisujemy pola klasy – this.ngIf oraz this.ngIfElse. Wstrzykujemy również serwis, który będzie weryfikować czy użytkownik posiada zadaną rolę – może być typowy auth.service, gdzie również jest trzymany profil użytkownika, wraz z jego rolami. Pamiętaj, że nazwa selektora musi być zgodna z nazwami inputów  (appHasRole, apphasRoleElse). Wpis nie zawiera opisu działania dyrektyw strukturalnych – jeśli nie są Ci znane, zapraszam do dedykowanego artykułu:

Angular – dyrektywy strukturalne

To jest całe rozwiązanie – używaj go śmiało z opcją „else” i tablicą wielu ról, którymi może dysponować użytkownik aplikacji. A może masz tylko profil użytkownika i admina i nie potrzebujesz tablicy parameterów z rolami ? Eksperymentuj! W takiej sytuacji wystarczy bezparametrowa dyrektywa *hasAdminRole lub *isAdmin.

Istnieje również pewien gotchas,  np. jeśli renderujesz dynamiczne komponenty  za pomocą ComponentFactoryResolver, to nie będziesz w stanie nałożyć dyrektywy strukturalnej jednocześnie z templateRef # (Angular na to nie pozwala). Musisz poczekać, aż na pewno element w DOM będzie dostępny i zawołać tworzenie komponentów w hooku ngAfterViewInit.

NIE ZADZIAŁA:

DOBRZE, ZADZIAŁA ;):

DEMO:

https://stackblitz.com/edit/angular-apgykt?embed=1&file=src/app/has-role.directive.ts

 

A kolejny wpis, o wykrywaniu niezamkniętych subskrybcji w RxJS 😉 Stay tuned!

3 Comments

  1. Michał Grontkowski

    Zrobiłem podobną funkcjonalność ale akurat ściągnąłem kawałek kodu *ngIf i go użyłem 🙂 Nie pomyślałem, że można dziedziczyć po *ngIf. Super sprawa 🙂

    • Tomasz Nastały

      hej, na razie martwy 🙂 praca na etacie i nad wlasnym startupem pochłoneła mnie do reszty, na pewno do końca wakacji nie będę blogować. Zapraszam na nowości od drugiej połowy września!

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *