-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauto-focus.directive.ts
More file actions
56 lines (48 loc) · 1.82 KB
/
auto-focus.directive.ts
File metadata and controls
56 lines (48 loc) · 1.82 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
import { AfterViewInit, Directive, ElementRef, inject, DOCUMENT } from '@angular/core'
import { isInputElement, LoggerService } from '@shiftcode/ngx-core'
import { Logger } from '@shiftcode/logger'
/**
* Standalone Autofocus Directive
* tries to set focus on host element in ngAfterViewInit lifecycle
* if initially not focusable, the directive sets `tabindex` to -1 and retries.
* -- will not remove the potentially set tabindex
*/
@Directive({
selector: '[scAutoFocus]',
standalone: true,
})
export class AutoFocusDirective implements AfterViewInit {
readonly element: HTMLElement = inject(ElementRef).nativeElement
private readonly document: Document = inject(DOCUMENT)
private readonly logger: Logger = inject(LoggerService).getInstance('AutoFocusDirective')
ngAfterViewInit(): void {
this.focus()
}
focus(): boolean {
if (ngDevMode) {
this.logger.debug('try set focus to', this.element)
if (this.isDisabled() || this.isHiddenInput()) {
this.logger.warn('you are trying to focus a disabled element or hidden input')
}
}
this.element.focus()
if (this.document.activeElement !== this.element) {
this.element.setAttribute('tabindex', '-1')
this.element.focus()
}
if (ngDevMode) {
if (this.document.activeElement !== this.element) {
this.logger.error('not able to focus the element', this.element)
}
}
return this.document.activeElement === this.element
}
private isDisabled() {
// using `matches` for the pseudo selector also correctly returns true when
// e.g. the directive is used in an input field inside a disabled fieldset
return this.element.hasAttribute('disabled') || this.element.matches(':disabled')
}
private isHiddenInput() {
return isInputElement(this.element) && this.element.type === 'hidden'
}
}