How to write a custom structural directive to display only authorized sections of a page in Angular
Abbas Ogaji
Posted on February 5, 2020
Imagine a scenario where you have a page or form that should only display certain sections or fields based on a user role or authority in an application. For this, you would probably need conditional statements that would drive your display. Traditional *ngIf directive could be used, but for this use-case, we will write a custom derivate with more features;
So let's go:
For our use-case, a user is provided with an array of viewable sections based on role/level/authority, so that a section of a page will only be displayed if it's included in the array.
const userViewableSections = ["bio-section", "friends-section", "posts-section"]
- Our custom directive name would be "isAuthorized"
- we would add an asterisk(*) to our directive name *isAuthorized to make use of Angular's microsyntax
- Our directive will be written like this;
import { Directive, TemplateRef,ViewContainerRef, Input, OnInit, OnChanges } from '@angular/core';
@Directive({ selector: '[isAuthorized]'})
export class IsAuthorizedDirective implements OnInit, OnChanges{
@Input() isAuthorizedIn : string[]
@Input() isAuthorized : string
private hasView = false;
constructor(private templateRef: TemplateRef<any>,
private vcr: ViewContainerRef) { }
ngOnInit() {
this.configureView()
}
ngOnChanges(){
this.configureView()
}
configureView(){
const isAuthorized = this.isAuthorizedIn.some(i => i == this.isAuthorized)
if (isAuthorized && !this.hasView) {
this.vcr.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (!isAuthorized && this.hasView) {
this.vcr.clear();
this.hasView = false;
}
}
}
Directive Breakdown:
TemplateRef and ViewContainerRef:
TemplateRef represents an embedded template that can be used to instantiate embedded views, so the HTML snippet that houses our directive becomes a templateRef which is then instantiated by the ViewContainerRef.
Microsyntax
Angular's microsyntax features provides us options to pass parameters with the format below;
*isAuthorized="'bio-section'; in : userViewableSections"
the string 'bio-section' is mapped to @Input() isAuthorized and "...; in : userViewableSections" maps the userViewableSections array to @Input() isAuthorizedIn; the microsytax will resolve the "in" to recognize a @Input() variable with "in" appended to the parent directive @Input in camel case format (i.e isAuthorized + In = @Input() isAuthorizedIn)
Summary
In summary, the directive displays our template if the string passed into @Input() isAuthorized, exists in array passed into @Input() isAuthorizedIn
See Screenshots below;
PAGE :
Check out the complete project on GitHub; Project Link
Posted on February 5, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 5, 2020