diff --git a/projects/angular-components/src/lib/search/search.component.ts b/projects/angular-components/src/lib/search/search.component.ts index fe6e783..dca57e3 100644 --- a/projects/angular-components/src/lib/search/search.component.ts +++ b/projects/angular-components/src/lib/search/search.component.ts @@ -9,12 +9,14 @@ import { Input, OnDestroy, OnInit, + AfterViewInit, ViewChild, } from '@angular/core'; import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { IconMagnifierComponent } from '../icons/icon-magnifier/icon-magnifier.component'; import { debounceTime, noop, Subject } from 'rxjs'; import { NgClass } from '@angular/common'; +import { FocusOnKeyUtil } from '../utils/focus-on-key.util'; export const SEARCH_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, @@ -31,9 +33,10 @@ export const SEARCH_CONTROL_VALUE_ACCESSOR = { changeDetection: ChangeDetectionStrategy.OnPush, providers: [SEARCH_CONTROL_VALUE_ACCESSOR], }) -export class SearchComponent implements OnInit, OnDestroy, ControlValueAccessor { +export class SearchComponent implements OnInit, AfterViewInit, OnDestroy, ControlValueAccessor { @Input() placeholder: string = 'Search...'; @Input() focusKey: string = '/'; + @Input({ transform: booleanAttribute }) forceFocus: boolean = false; @Input({ transform: booleanAttribute }) focusKeyEnabled: boolean = true; @Input({ transform: booleanAttribute }) slim: boolean = false; @ViewChild('input') _inputElement!: ElementRef; @@ -43,6 +46,12 @@ export class SearchComponent implements OnInit, OnDestroy, ControlValueAccessor private _value: string = ''; private _disabled: boolean = false; + private focusKeyUtil = new FocusOnKeyUtil({ + key: '/', + ctrl: false, + shift: false, + force: false, + }); @Input() get value(): string { @@ -70,9 +79,16 @@ export class SearchComponent implements OnInit, OnDestroy, ControlValueAccessor this.value = value; this._onChange(value); }); + this.focusKeyUtil.updateConfig({ + key: this.focusKey, + force: this.forceFocus, + }); + } + ngAfterViewInit(): void { if (this.focusKeyEnabled) { - window.addEventListener('keyup', this._onKeyEvent.bind(this), true); + this.focusKeyUtil.setFocusElement(this._inputElement.nativeElement); + this.focusKeyUtil.enable(); } } @@ -80,7 +96,7 @@ export class SearchComponent implements OnInit, OnDestroy, ControlValueAccessor this.searchSubject.complete(); if (this.focusKeyEnabled) { - window.removeEventListener('keyup', this._onKeyEvent, true); + this.focusKeyUtil?.disable(); } } @@ -114,11 +130,4 @@ export class SearchComponent implements OnInit, OnDestroy, ControlValueAccessor protected _onInteractionEvent(event: Event): void { event.stopPropagation(); } - - protected _onKeyEvent(event: KeyboardEvent): void { - if (event.key === this.focusKey) { - this._inputElement.nativeElement.focus(); - event.preventDefault(); - } - } } diff --git a/projects/angular-components/src/lib/utils/focus-on-key.util.ts b/projects/angular-components/src/lib/utils/focus-on-key.util.ts new file mode 100644 index 0000000..5ad1a1e --- /dev/null +++ b/projects/angular-components/src/lib/utils/focus-on-key.util.ts @@ -0,0 +1,39 @@ +export type FocusOnKeyConfig = { + key: string; + ctrl: boolean; + shift: boolean; + force: boolean; +}; + +export class FocusOnKeyUtil { + constructor( + private config: FocusOnKeyConfig = { key: 'k', ctrl: true, shift: false, force: false }, + private focusElement?: HTMLElement, + ) {} + + setFocusElement(focusElement: HTMLElement): void { + this.focusElement = focusElement; + } + + updateConfig(config: Partial): void { + this.config = { ...this.config, ...config }; + } + + enable(): void { + if (!this.focusElement) console.warn('No focus element set'); + window.addEventListener(this.config.force ? 'keydown' : 'keyup', this._onKeyEvent.bind(this)); + } + + disable(): void { + window.removeEventListener('keydown', this._onKeyEvent); + window.removeEventListener('keyup', this._onKeyEvent); + } + + private _onKeyEvent(event: KeyboardEvent): void { + if (!this.focusElement) return; + if (event.key === this.config.key) { + this.focusElement.focus(); + event.preventDefault(); + } + } +} diff --git a/projects/angular-components/src/public_api.ts b/projects/angular-components/src/public_api.ts index 20dbb9a..8b9a29d 100644 --- a/projects/angular-components/src/public_api.ts +++ b/projects/angular-components/src/public_api.ts @@ -12,3 +12,4 @@ export * from './lib/datatable/dt-content.directive'; // helper classes export * from './lib/icons/icon-base'; +export * from './lib/utils/focus-on-key.util'; diff --git a/src/app/app.component.html b/src/app/app.component.html index 8f52c8b..09adb48 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -24,7 +24,7 @@

Checkbox

  • Search

    - +