mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-21 11:35:34 +01:00
[CL-161] Update bit-search support autofocus (#7272)
appAutofocus currently doesn't work on the bit-search component. This PR resolves this issue by introducing a FocusableElement interface components can implement, which is respected by the autofocus directive.
This commit is contained in:
parent
7112f44375
commit
280cb7e2c0
@ -1,30 +0,0 @@
|
||||
import { Directive, ElementRef, Input, NgZone } from "@angular/core";
|
||||
import { take } from "rxjs/operators";
|
||||
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
@Directive({
|
||||
selector: "[appAutofocus]",
|
||||
})
|
||||
export class AutofocusDirective {
|
||||
@Input() set appAutofocus(condition: boolean | string) {
|
||||
this.autofocus = condition === "" || condition === true;
|
||||
}
|
||||
|
||||
private autofocus: boolean;
|
||||
|
||||
constructor(
|
||||
private el: ElementRef,
|
||||
private ngZone: NgZone,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (!Utils.isMobileBrowser && this.autofocus) {
|
||||
if (this.ngZone.isStable) {
|
||||
this.el.nativeElement.focus();
|
||||
} else {
|
||||
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.el.nativeElement.focus());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,12 +2,13 @@ import { CommonModule, DatePipe } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
|
||||
import { AutofocusDirective } from "@bitwarden/components";
|
||||
|
||||
import { CalloutComponent } from "./components/callout.component";
|
||||
import { BitwardenToastModule } from "./components/toastr.component";
|
||||
import { A11yInvalidDirective } from "./directives/a11y-invalid.directive";
|
||||
import { A11yTitleDirective } from "./directives/a11y-title.directive";
|
||||
import { ApiActionDirective } from "./directives/api-action.directive";
|
||||
import { AutofocusDirective } from "./directives/autofocus.directive";
|
||||
import { BoxRowDirective } from "./directives/box-row.directive";
|
||||
import { CopyClickDirective } from "./directives/copy-click.directive";
|
||||
import { CopyTextDirective } from "./directives/copy-text.directive";
|
||||
|
54
libs/components/src/input/autofocus.directive.ts
Normal file
54
libs/components/src/input/autofocus.directive.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { Directive, ElementRef, Input, NgZone, Optional } from "@angular/core";
|
||||
import { take } from "rxjs/operators";
|
||||
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
/**
|
||||
* Interface for implementing focusable components. Used by the AutofocusDirective.
|
||||
*/
|
||||
export abstract class FocusableElement {
|
||||
focus: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Directive to focus an element.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* If the component provides the `FocusableElement` interface, the `focus`
|
||||
* method will be called. Otherwise, the native element will be focused.
|
||||
*/
|
||||
@Directive({
|
||||
selector: "[appAutofocus], [bitAutofocus]",
|
||||
})
|
||||
export class AutofocusDirective {
|
||||
@Input() set appAutofocus(condition: boolean | string) {
|
||||
this.autofocus = condition === "" || condition === true;
|
||||
}
|
||||
|
||||
private autofocus: boolean;
|
||||
|
||||
constructor(
|
||||
private el: ElementRef,
|
||||
private ngZone: NgZone,
|
||||
@Optional() private focusableElement: FocusableElement,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (!Utils.isMobileBrowser && this.autofocus) {
|
||||
if (this.ngZone.isStable) {
|
||||
this.focus();
|
||||
} else {
|
||||
this.ngZone.onStable.pipe(take(1)).subscribe(this.focus.bind(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private focus() {
|
||||
if (this.focusableElement) {
|
||||
this.focusableElement.focus();
|
||||
} else {
|
||||
this.el.nativeElement.focus();
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
export * from "./input.module";
|
||||
export * from "./autofocus.directive";
|
||||
|
@ -8,6 +8,7 @@
|
||||
<i class="bwi bwi-search bwi-fw tw-text-muted"></i>
|
||||
</label>
|
||||
<input
|
||||
#input
|
||||
bitInput
|
||||
type="search"
|
||||
[id]="id"
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { Component, ElementRef, Input, ViewChild } from "@angular/core";
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
|
||||
|
||||
import { FocusableElement } from "../input/autofocus.directive";
|
||||
|
||||
let nextId = 0;
|
||||
|
||||
@Component({
|
||||
@ -12,18 +14,28 @@ let nextId = 0;
|
||||
multi: true,
|
||||
useExisting: SearchComponent,
|
||||
},
|
||||
{
|
||||
provide: FocusableElement,
|
||||
useExisting: SearchComponent,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class SearchComponent implements ControlValueAccessor {
|
||||
export class SearchComponent implements ControlValueAccessor, FocusableElement {
|
||||
private notifyOnChange: (v: string) => void;
|
||||
private notifyOnTouch: () => void;
|
||||
|
||||
@ViewChild("input") private input: ElementRef<HTMLInputElement>;
|
||||
|
||||
protected id = `search-id-${nextId++}`;
|
||||
protected searchText: string;
|
||||
|
||||
@Input() disabled: boolean;
|
||||
@Input() placeholder: string;
|
||||
|
||||
focus() {
|
||||
this.input.nativeElement.focus();
|
||||
}
|
||||
|
||||
onChange(searchText: string) {
|
||||
if (this.notifyOnChange != undefined) {
|
||||
this.notifyOnChange(searchText);
|
||||
|
Loading…
Reference in New Issue
Block a user