Skip to content

Instantly share code, notes, and snippets.

@cbejensen
Last active September 22, 2020 23:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbejensen/b6fa43b5bb34902d3f3b3f7328c6bb11 to your computer and use it in GitHub Desktop.
Save cbejensen/b6fa43b5bb34902d3f3b3f7328c6bb11 to your computer and use it in GitHub Desktop.
Focusable Base Class in Angular
import { AfterViewInit, Directive, ElementRef, Input, ViewChild } from '@angular/core';
import { FocusableOption, FocusOrigin } from '@angular/cdk/a11y';
/**
* A base class that can be extended by any component to allow its parent to focus it. All the component needs to do
* is set a template reference variable of `focusable` on whichever input it should focus when the parent wants to
* focus it. You could even set `focusable` on another custom component, so long as it also extends this class.
*
* @example
* ```html
* <!-- component template -->
* <input #focusable />
* ```
* ```typescript
* // parent component
* export class ParentComponent {
* @ViewChild(MyComponent) myComp;
*
* someMethod = () => this.myComp.focus();
* }
* ```
*
* You can also autofocus.
* ```html
* <!-- parent component template -->
* <my-component [autofocus]="true"></my-component>
* ```
*/
@Directive()
export abstract class Focusable implements FocusableOption, AfterViewInit {
@Input() autofocus: boolean;
@ViewChild('focusable') private _focusable: FocusableOption | ElementRef;
private _focusAfterViewInit = false;
ngAfterViewInit(): void {
if (this.autofocus || this._focusAfterViewInit) {
this.focus();
}
}
focus = (focusOrigin?: FocusOrigin): void => {
if (!this._focusable) {
this._focusAfterViewInit = true;
return;
}
const { focus } = this._focusable as FocusableOption;
if (focus) {
// `focusable` is a component.
focus(focusOrigin);
} else {
// `focusable` is a native element.
(this._focusable as ElementRef).nativeElement?.focus();
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment