Angular Snippets

Disable components using directive

angular directives

The code snippet below shows how to disable (angular material) components if the shouldDisable$ stream from the ExampleService emits true. This can be a useful solution when we want to block actions when the user does not have the appropriate permissions resulting from:

  • user role
  • a feature that is blocked for the user etc.

(*) DestroyedDirective was implemented according to the idea of Kristiyan Kostadinov.

@Directive({
  selector: "[disableInteractiveElements]",
  standalone: true,
  hostDirectives: [DestroyedDirective],
})
export class DisableInteractiveElementsDirective implements OnInit {
  private readonly destroyed$ = inject(DestroyedDirective).destroyed$;

  constructor(
    private readonly service: ExampleService,
    private readonly elementRef: ElementRef,
    @Optional() @Self() private readonly button: MatButton,
    @Optional() @Self() private readonly select: MatSelect
  ) {}

  ngOnInit(): void {
    this.service.shouldDisable$
      .pipe(takeUntil(this.destroyed$))
      .subscribe((shouldDisable) => {
        if (this.button) {
          this.button.disabled = shouldDisable;
        } else if (this.select) {
          this.select.disabled = shouldDisable;
        } else if (
          this.elementRef.nativeElement &&
          "disabled" in this.elementRef.nativeElement
        ) {
          this.elementRef.nativeElement.disabled = shouldDisable;
        }
      });
  }
}

Usage in template:

<button mat-button mat-raised-button>Always available</button>
<button disableInteractiveElements mat-button mat-raised-button>
  Could be disabled
</button>
<mat-select disableInteractiveElements placeholder="Settings">
  <mat-option value="'setting1'">Setting 1</mat-option>
  <mat-option value="'setting2'">Setting 2</mat-option>
</mat-select>
<input disableInteractiveElements type="text" />

In the case shown above, the first button will always be active, while the other elements, i.e. the second button, select and input, will be active if service.shouldDisable$ emits false.

Back to snippets