Skip to content

Commit cfba963

Browse files
authored
feat: Disable components using directive (santoshyadavdev#19)
* feat: Disable components using directive * feat: add information about DestroyedDirective + add ElementRef * feat: clean up redundant information
1 parent 1b68d23 commit cfba963

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
title: Disable components using directive
3+
description: "Example of directive to disable interactive components when a certain condition is met."
4+
tags: ["angular", "directives"]
5+
pubDate: Feb 25, 2023
6+
contributedBy: "@pawelkubiakdev"
7+
---
8+
9+
The code snippet below shows how to disable (angular material) components if the shouldDisable$ stream from the ExampleService emits true.
10+
This can be a useful solution when we want to block actions when the user does not have the appropriate permissions resulting from:
11+
- user role
12+
- a feature that is blocked for the user etc.
13+
14+
(*) `DestroyedDirective` was implemented according to the idea of [Kristiyan Kostadinov](https://twitter.com/_crisbeto/status/1582475442715385858).
15+
16+
17+
```typescript
18+
@Directive({
19+
selector: '[disableInteractiveElements]',
20+
standalone: true,
21+
hostDirectives: [DestroyedDirective]
22+
})
23+
export class DisableInteractiveElementsDirective implements OnInit {
24+
private readonly destroyed$ = inject(DestroyedDirective).destroyed$;
25+
26+
constructor(private readonly service: ExampleService,
27+
private readonly elementRef: ElementRef,
28+
@Optional() @Self() private readonly button: MatButton,
29+
@Optional() @Self() private readonly select: MatSelect) {}
30+
31+
ngOnInit(): void {
32+
this.service.shouldDisable$
33+
.pipe(takeUntil(this.destroyed$))
34+
.subscribe((shouldDisable) => {
35+
if (this.button) {
36+
this.button.disabled = shouldDisable;
37+
} else if (this.select) {
38+
this.select.disabled = shouldDisable;
39+
} else if (this.elementRef.nativeElement && ('disabled' in this.elementRef.nativeElement)) {
40+
this.elementRef.nativeElement.disabled = shouldDisable;
41+
}
42+
});
43+
}
44+
}
45+
```
46+
47+
Usage in template:
48+
49+
```html
50+
<button mat-button mat-raised-button>Always available</button>
51+
<button disableInteractiveElements mat-button mat-raised-button>Could be disabled</button>
52+
<mat-select disableInteractiveElements placeholder="Settings">
53+
<mat-option value="'setting1'">Setting 1</mat-option>
54+
<mat-option value="'setting2'">Setting 2</mat-option>
55+
</mat-select>
56+
<input disableInteractiveElements type="text" />
57+
```
58+
59+
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.

0 commit comments

Comments
 (0)