-
Notifications
You must be signed in to change notification settings - Fork 138
Expand file tree
/
Copy pathuiSrefActive.ts
More file actions
129 lines (125 loc) · 4.36 KB
/
uiSrefActive.ts
File metadata and controls
129 lines (125 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { Directive, Input, ElementRef, Host, Renderer2 } from '@angular/core';
import { UISrefStatus, SrefStatus } from './uiSrefStatus';
import { Subscription } from 'rxjs';
/**
* A directive that adds a CSS class when its associated `uiSref` link is active.
*
* ### Purpose
*
* This directive should be paired with one (or more) [[UISref]] directives.
* It will apply a CSS class to its element when the state the `uiSref` targets is activated.
*
* This can be used to create navigation UI where the active link is highlighted.
*
* ### Selectors
*
* - `[uiSrefActive]`: When this selector is used, the class is added when the target state or any
* child of the target state is active
* - `[uiSrefActiveEq]`: When this selector is used, the class is added when the target state is
* exactly active (the class is not added if a child of the target state is active).
*
* ### Inputs
*
* - `uiSrefActive`/`uiSrefActiveEq`: one or more CSS classes to add to the element, when the `uiSref` is active
*
* #### Example:
* The anchor tag has the `active` class added when the `foo` state is active.
* ```html
* <a uiSref="foo" uiSrefActive="active">Foo</a>
* ```
*
* ### Matching parameters
*
* If the `uiSref` includes parameters, the current state must be active, *and* the parameter values must match.
*
* #### Example:
* The first anchor tag has the `active` class added when the `foo.bar` state is active and the `id` parameter
* equals 25.
* The second anchor tag has the `active` class added when the `foo.bar` state is active and the `id` parameter
* equals 32.
* ```html
* <a uiSref="foo.bar" [uiParams]="{ id: 25 }" uiSrefActive="active">Bar #25</a>
* <a uiSref="foo.bar" [uiParams]="{ id: 32 }" uiSrefActive="active">Bar #32</a>
* ```
*
* #### Example:
* A list of anchor tags are created for a list of `bar` objects.
* An anchor tag will have the `active` class when `foo.bar` state is active and the `id` parameter matches
* that object's `id`.
* ```html
* <li *ngFor="let bar of bars">
* <a uiSref="foo.bar" [uiParams]="{ id: bar.id }" uiSrefActive="active">Bar #{{ bar.id }}</a>
* </li>
* ```
*
* ### Multiple uiSrefs
*
* A single `uiSrefActive` can be used for multiple `uiSref` links.
* This can be used to create (for example) a drop down navigation menu, where the menui is highlighted
* if *any* of its inner links are active.
*
* The `uiSrefActive` should be placed on an ancestor element of the `uiSref` list.
* If anyof the `uiSref` links are activated, the class will be added to the ancestor element.
*
* #### Example:
* This is a dropdown nagivation menu for "Admin" states.
* When any of `admin.users`, `admin.groups`, `admin.settings` are active, the `<li>` for the dropdown
* has the `dropdown-child-active` class applied.
* Additionally, the active anchor tag has the `active` class applied.
* ```html
* <ul class="dropdown-menu">
* <li uiSrefActive="dropdown-child-active" class="dropdown admin">
* Admin
* <ul>
* <li><a uiSref="admin.users" uiSrefActive="active">Users</a></li>
* <li><a uiSref="admin.groups" uiSrefActive="active">Groups</a></li>
* <li><a uiSref="admin.settings" uiSrefActive="active">Settings</a></li>
* </ul>
* </li>
* </ul>
* ```
*/
@Directive({
selector: '[uiSrefActive],[uiSrefActiveEq]',
hostDirectives: [
{
directive: UISrefStatus,
outputs: ['uiSrefStatus'],
},
],
standalone: true,
})
export class UISrefActive {
private _classes: string[] = [];
@Input('uiSrefActive')
set active(val: string) {
this._classes = val.split(/\s+/);
}
private _classesEq: string[] = [];
@Input('uiSrefActiveEq')
set activeEq(val: string) {
this._classesEq = val.split(/\s+/);
}
private _subscription: Subscription;
constructor(uiSrefStatus: UISrefStatus, rnd: Renderer2, @Host() host: ElementRef) {
this._subscription = uiSrefStatus.uiSrefStatus.subscribe((next: SrefStatus) => {
this._classes.forEach((cls) => {
if (next.active) {
rnd.addClass(host.nativeElement, cls);
} else {
rnd.removeClass(host.nativeElement, cls);
}
});
this._classesEq.forEach((cls) => {
if (next.exact) {
rnd.addClass(host.nativeElement, cls);
} else {
rnd.removeClass(host.nativeElement, cls);
}
});
});
}
ngOnDestroy() {
this._subscription.unsubscribe();
}
}