How to write a custom structural directive to display only authorized sections of a page in Angular
Tags: angular, typescript, tutorial, javascript
Published: 2020-02-05 09:55:09

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.

```typescript
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](https://angular.io/guide/structural-directives#microsyntax)
- Our directive will be written like this;

```typescript

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 :

![custom-dir-html-page](https://user-images.githubusercontent.com/34817010/73829652-a3e4bd00-4803-11ea-9d54-3df6e832005c.PNG)

COMPONENT HTML
![angular-html-ngIf](https://user-images.githubusercontent.com/34817010/73830251-a267c480-4804-11ea-9dbe-c5786ae1b16f.png)


Check out the complete project on GitHub; [Project Link](https://github.com/abbasogaji/custom-ngIf-directive)