angular-input-focus
Version:
An Angular focus attribute directive.
104 lines • 11.6 kB
JavaScript
import { Directive, Input, Inject, PLATFORM_ID } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { isPlatformBrowser } from '@angular/common';
import * as i0 from "@angular/core";
/**
* An angular focus directive.
* ## Usage
* For autofocus-like functionality, use like this:
* <input [libFocus]="true"...>
*
* You can also pass an `EventEmitter<boolean>` as `setFocus` like so:
* <input [libFocus]="false" [setFocus]="focusEvent">`
*
* Whenever your `focusEvent` emits a value, your element will focus/blur depending on
* whether it is true or false.
*/
export class AngularInputFocusDirective {
constructor(el, cd, zone, platformId) {
this.el = el;
this.cd = cd;
this.zone = zone;
/**
* Indicates whether the current platform is a web browser. Used because our `focus`
* implementation is specific to the DOM. Set in constructor.
*/
this.isRunningInBrowser = null;
/**
* When set to true, directive will mimick `autofocus` like functionality for your input.
*/
this.focus = false;
/**
* Set to true if you want to run outside angular and skip change detection. If you're not using
* Angular Material, you can pretty safely set to "true".
*/
this.skipChangeDetection = false;
/**
* A subject that will emit a value when we should unsubscribe to our observables.
*/
this.killSubscriptions = new Subject();
this.isRunningInBrowser = isPlatformBrowser(platformId);
}
/**
* When you emit a true value, the input will gain focus. If false, the input will blur.
*/
set setFocus(value) {
// Unsubscribe from any previous subs
this.killSubscriptions.next();
value.pipe(takeUntil(this.killSubscriptions)).subscribe(focus => this.setFocusOnElement(focus));
}
/**
* Set the focus on the target element.
* @param focus Should the element have focus?
*/
setFocusOnElement(focus) {
// If we aren't in a browser, there's nothing to do since our implementation is DOM-specific.
// If we don't have a nativeElement, we have nothing to do either.
if (this.isRunningInBrowser === false || !this.el.nativeElement) {
return;
}
// Running outside angular zone to not trigger change detection unless we want to.
this.zone.runOutsideAngular(() => {
if (focus === true) {
this.el.nativeElement.focus();
}
else {
this.el.nativeElement.blur();
}
if (!this.skipChangeDetection) {
this.cd.detectChanges();
}
});
}
ngAfterViewInit() {
if (this.focus === true) {
// After view init, if focus is set, focus element to mimick autofocus functionality.
this.setFocusOnElement(true);
}
}
ngOnDestroy() {
this.killSubscriptions.next();
this.killSubscriptions.complete();
}
}
AngularInputFocusDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AngularInputFocusDirective, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive });
AngularInputFocusDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.6", type: AngularInputFocusDirective, selector: "[libFocus]", inputs: { focus: ["libFocus", "focus"], setFocus: "setFocus", skipChangeDetection: "skipChangeDetection" }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: AngularInputFocusDirective, decorators: [{
type: Directive,
args: [{
selector: '[libFocus]'
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }]; }, propDecorators: { focus: [{
type: Input,
args: ['libFocus']
}], setFocus: [{
type: Input,
args: ['setFocus']
}], skipChangeDetection: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1pbnB1dC1mb2N1cy5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWlucHV0LWZvY3VzL3NyYy9saWIvYW5ndWxhci1pbnB1dC1mb2N1cy5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBYyxLQUFLLEVBQW1DLE1BQU0sRUFBRSxXQUFXLEVBQW9DLE1BQU0sZUFBZSxDQUFDO0FBQ3JKLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDOztBQU1wRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sT0FBTywwQkFBMEI7SUF1RHJDLFlBQW9CLEVBQWMsRUFBVSxFQUFxQixFQUFVLElBQVksRUFBdUIsVUFBa0I7UUFBNUcsT0FBRSxHQUFGLEVBQUUsQ0FBWTtRQUFVLE9BQUUsR0FBRixFQUFFLENBQW1CO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBUTtRQXREdkY7OztXQUdHO1FBQ0ssdUJBQWtCLEdBQVksSUFBSSxDQUFDO1FBRTNDOztXQUVHO1FBQ2dCLFVBQUssR0FBRyxLQUFLLENBQUM7UUFXakM7OztXQUdHO1FBQ00sd0JBQW1CLEdBQUcsS0FBSyxDQUFDO1FBRXJDOztXQUVHO1FBQ0ssc0JBQWlCLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQTBCeEMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzFELENBQUM7SUE3Q0Q7O09BRUc7SUFDSCxJQUF1QixRQUFRLENBQUMsS0FBNEI7UUFDMUQscUNBQXFDO1FBQ3JDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM5QixLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFhRDs7O09BR0c7SUFDSyxpQkFBaUIsQ0FBQyxLQUFjO1FBQ3RDLDZGQUE2RjtRQUM3RixrRUFBa0U7UUFDbEUsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEtBQUssS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUU7WUFDL0QsT0FBTztTQUNSO1FBQ0Qsa0ZBQWtGO1FBQ2xGLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFO1lBQy9CLElBQUksS0FBSyxLQUFLLElBQUksRUFBRTtnQkFDbEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7YUFDL0I7aUJBQU07Z0JBQ0wsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7YUFDOUI7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFO2dCQUM3QixJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxDQUFDO2FBQ3pCO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBTUQsZUFBZTtRQUNiLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUU7WUFDdkIscUZBQXFGO1lBQ3JGLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUM5QjtJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNwQyxDQUFDOzt1SEFyRVUsMEJBQTBCLG1HQXVENEQsV0FBVzsyR0F2RGpHLDBCQUEwQjsyRkFBMUIsMEJBQTBCO2tCQWhCdEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsWUFBWTtpQkFDdkI7OzBCQXFFMkYsTUFBTTsyQkFBQyxXQUFXOzRDQTdDekYsS0FBSztzQkFBdkIsS0FBSzt1QkFBQyxVQUFVO2dCQUtNLFFBQVE7c0JBQTlCLEtBQUs7dUJBQUMsVUFBVTtnQkFVUixtQkFBbUI7c0JBQTNCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIElucHV0LCBOZ1pvbmUsIEV2ZW50RW1pdHRlciwgT25EZXN0cm95LCBJbmplY3QsIFBMQVRGT1JNX0lELCBBZnRlclZpZXdJbml0LCBDaGFuZ2VEZXRlY3RvclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbbGliRm9jdXNdJ1xufSlcblxuLyoqXG4gKiBBbiBhbmd1bGFyIGZvY3VzIGRpcmVjdGl2ZS5cbiAqICMjIFVzYWdlXG4gKiBGb3IgYXV0b2ZvY3VzLWxpa2UgZnVuY3Rpb25hbGl0eSwgdXNlIGxpa2UgdGhpczpcbiAqIDxpbnB1dCBbbGliRm9jdXNdPVwidHJ1ZVwiLi4uPlxuICogXG4gKiBZb3UgY2FuIGFsc28gcGFzcyBhbiBgRXZlbnRFbWl0dGVyPGJvb2xlYW4+YCBhcyBgc2V0Rm9jdXNgIGxpa2Ugc286XG4gKiA8aW5wdXQgW2xpYkZvY3VzXT1cImZhbHNlXCIgW3NldEZvY3VzXT1cImZvY3VzRXZlbnRcIj5gXG4gKiBcbiAqIFdoZW5ldmVyIHlvdXIgYGZvY3VzRXZlbnRgIGVtaXRzIGEgdmFsdWUsIHlvdXIgZWxlbWVudCB3aWxsIGZvY3VzL2JsdXIgZGVwZW5kaW5nIG9uXG4gKiB3aGV0aGVyIGl0IGlzIHRydWUgb3IgZmFsc2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBBbmd1bGFySW5wdXRGb2N1c0RpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciB0aGUgY3VycmVudCBwbGF0Zm9ybSBpcyBhIHdlYiBicm93c2VyLiBVc2VkIGJlY2F1c2Ugb3VyIGBmb2N1c2AgXG4gICAqIGltcGxlbWVudGF0aW9uIGlzIHNwZWNpZmljIHRvIHRoZSBET00uIFNldCBpbiBjb25zdHJ1Y3Rvci5cbiAgICovXG4gIHByaXZhdGUgaXNSdW5uaW5nSW5Ccm93c2VyOiBib29sZWFuID0gbnVsbDtcblxuICAvKipcbiAgICogV2hlbiBzZXQgdG8gdHJ1ZSwgZGlyZWN0aXZlIHdpbGwgbWltaWNrIGBhdXRvZm9jdXNgIGxpa2UgZnVuY3Rpb25hbGl0eSBmb3IgeW91ciBpbnB1dC5cbiAgICovXG4gIEBJbnB1dCgnbGliRm9jdXMnKSBmb2N1cyA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBXaGVuIHlvdSBlbWl0IGEgdHJ1ZSB2YWx1ZSwgdGhlIGlucHV0IHdpbGwgZ2FpbiBmb2N1cy4gSWYgZmFsc2UsIHRoZSBpbnB1dCB3aWxsIGJsdXIuXG4gICAqL1xuICBASW5wdXQoJ3NldEZvY3VzJykgc2V0IHNldEZvY3VzKHZhbHVlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4pIHtcbiAgICAvLyBVbnN1YnNjcmliZSBmcm9tIGFueSBwcmV2aW91cyBzdWJzXG4gICAgdGhpcy5raWxsU3Vic2NyaXB0aW9ucy5uZXh0KCk7XG4gICAgdmFsdWUucGlwZSh0YWtlVW50aWwodGhpcy5raWxsU3Vic2NyaXB0aW9ucykpLnN1YnNjcmliZShmb2N1cyA9PiB0aGlzLnNldEZvY3VzT25FbGVtZW50KGZvY3VzKSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRvIHRydWUgaWYgeW91IHdhbnQgdG8gcnVuIG91dHNpZGUgYW5ndWxhciBhbmQgc2tpcCBjaGFuZ2UgZGV0ZWN0aW9uLiBJZiB5b3UncmUgbm90IHVzaW5nXG4gICAqIEFuZ3VsYXIgTWF0ZXJpYWwsIHlvdSBjYW4gcHJldHR5IHNhZmVseSBzZXQgdG8gXCJ0cnVlXCIuXG4gICAqL1xuICBASW5wdXQoKSBza2lwQ2hhbmdlRGV0ZWN0aW9uID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEEgc3ViamVjdCB0aGF0IHdpbGwgZW1pdCBhIHZhbHVlIHdoZW4gd2Ugc2hvdWxkIHVuc3Vic2NyaWJlIHRvIG91ciBvYnNlcnZhYmxlcy5cbiAgICovXG4gIHByaXZhdGUga2lsbFN1YnNjcmlwdGlvbnMgPSBuZXcgU3ViamVjdCgpO1xuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGZvY3VzIG9uIHRoZSB0YXJnZXQgZWxlbWVudC5cbiAgICogQHBhcmFtIGZvY3VzIFNob3VsZCB0aGUgZWxlbWVudCBoYXZlIGZvY3VzP1xuICAgKi9cbiAgcHJpdmF0ZSBzZXRGb2N1c09uRWxlbWVudChmb2N1czogYm9vbGVhbikge1xuICAgIC8vIElmIHdlIGFyZW4ndCBpbiBhIGJyb3dzZXIsIHRoZXJlJ3Mgbm90aGluZyB0byBkbyBzaW5jZSBvdXIgaW1wbGVtZW50YXRpb24gaXMgRE9NLXNwZWNpZmljLlxuICAgIC8vIElmIHdlIGRvbid0IGhhdmUgYSBuYXRpdmVFbGVtZW50LCB3ZSBoYXZlIG5vdGhpbmcgdG8gZG8gZWl0aGVyLlxuICAgIGlmICh0aGlzLmlzUnVubmluZ0luQnJvd3NlciA9PT0gZmFsc2UgfHwgIXRoaXMuZWwubmF0aXZlRWxlbWVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBSdW5uaW5nIG91dHNpZGUgYW5ndWxhciB6b25lIHRvIG5vdCB0cmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb24gdW5sZXNzIHdlIHdhbnQgdG8uXG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIGlmIChmb2N1cyA9PT0gdHJ1ZSkge1xuICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5ibHVyKCk7XG4gICAgICB9XG4gICAgICBpZiAoIXRoaXMuc2tpcENoYW5nZURldGVjdGlvbikge1xuICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsIHByaXZhdGUgY2Q6IENoYW5nZURldGVjdG9yUmVmLCBwcml2YXRlIHpvbmU6IE5nWm9uZSwgQEluamVjdChQTEFURk9STV9JRCkgcGxhdGZvcm1JZDogc3RyaW5nKSB7XG4gICAgdGhpcy5pc1J1bm5pbmdJbkJyb3dzZXIgPSBpc1BsYXRmb3JtQnJvd3NlcihwbGF0Zm9ybUlkKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICBpZiAodGhpcy5mb2N1cyA9PT0gdHJ1ZSkge1xuICAgICAgLy8gQWZ0ZXIgdmlldyBpbml0LCBpZiBmb2N1cyBpcyBzZXQsIGZvY3VzIGVsZW1lbnQgdG8gbWltaWNrIGF1dG9mb2N1cyBmdW5jdGlvbmFsaXR5LlxuICAgICAgdGhpcy5zZXRGb2N1c09uRWxlbWVudCh0cnVlKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLmtpbGxTdWJzY3JpcHRpb25zLm5leHQoKTtcbiAgICB0aGlzLmtpbGxTdWJzY3JpcHRpb25zLmNvbXBsZXRlKCk7XG4gIH1cbn0iXX0=