Autofocus on Angular Form Field
Tags: angular, webdev
Published: 2022-09-12 13:31:44

Autofocus is a simple HTML attribute, but doesn’t work as expected with Angular apps. Let’s learn why with some different approaches to solve the problem!

## Autofocus Attribute

Add the autofocus attribute to an Angular input form field.

```html
<input type="text" id="firstName" name="firstName" formControlName="firstName" autofocus>
```

If you refresh the page, you will see that the form field has focus. Problem solved right?! Not so fast!

Try starting on a different page first and then navigating to the page with the form. The field has no focus. What happened?

Autofocus happens as soon as the page is loaded. An Angular application is a single page application (SPA). Once that single page is loaded, that’s it! You’ve lost your chance to bring focus to any future navigation to other pages.

So what can we do? Read on!

## Template Variable

Create a template variable on the input field called **firstNameField**. Remember that template variables are prefixed with a pound sign.

```html
<input type="text" id="firstName" name="firstName" formControlName="firstName" #firstNameField>
```

Within the component, you’ll need to import the following:

```javascript
import { AfterViewInit, ElementRef, ViewChild } from '@angular/core';
```

We want to access the input field from the view. We can use [ViewChild](https://angular.io/api/core/ViewChild) and reference the template variable we previously created called **firstNameField**. Then give it a name also called **firstNameField**, though it doesn’t have to be. We’ll define it’s type to be [ElementRef](https://angular.io/api/core/ElementRef), specifically an HTML input element.

```javascript
@ViewChild('firstNameField') firstNameField: ElementRef<HTMLInputElement>;
```

Your first thought might be to do something within the [OnInit](https://angular.io/api/core/OnInit) lifecycle hook. For this particular scenario, that won’t work. We need to make sure the form field exists on the page before trying to do anything with it. For that we need the [AfterViewInit](https://angular.io/api/core/AfterViewInit) lifecycle hook.

Make sure to implement AfterViewInit on your component.

```javascript
export class ExampleComponent implements AfterViewInit, OnInit {
  ...
}
```

Within the **ngAfterViewInit** lifecycle hook, let’s access the underlying native element and call the focus function.

```javascript
ngAfterViewInit() {
  this.firstNameField.nativeElement.focus();
}
```

Try starting on a different page first and then navigating to the page with the form. The form field now has focus!

Now imagine you had other form fields where you wanted to do this same thing. It gets a little repetitive doing the above changes for each component. That’s where an Angular directive can help!

## Autofocus Directive

Create the following directive.

```javascript
import { AfterViewInit, Directive, ElementRef } from '@angular/core';
 
@Directive({
  selector: '[appAutofocus]'
})
export class AutofocusDirective implements AfterViewInit {
  constructor(private element: ElementRef<HTMLInputElement>) { }
 
  ngAfterViewInit(): void {
    this.element.nativeElement.focus();
  }
}
```

We’re doing something similar here like we did in the component. We use the AfterViewInit lifecycle hook to bring focus to the element.

To make this directive usable across any module, let’s create it as its own module so it can be imported into any module where it’s needed.

```javascript
import { NgModule } from '@angular/core';
 
import { AutofocusDirective } from './autofocus.directive';
 
@NgModule({
  declarations: [AutofocusDirective],
  exports: [AutofocusDirective]
})
export class AutofocusDirectiveModule { }
```

To use the directive, first import it into the module where you want to use it.

```javascript
import { AutofocusDirectiveModule } from 'path/to/autofocus.directive.module';
 
@NgModule({
  ...
  imports: [
    ...
    AutofocusDirectiveModule,
    ...
  ]
})
export class ExampleModule { }
```

Add the directive attribute, which is called **appAutofocus**, to the input field.

```html
<input type="text" id="firstName" name="firstName" formControlName="firstName" appAutofocus>
```

Instead of doing the steps outlined in the prior Template Variable section, you can now reuse this directive wherever you need to add focus to a form field!

---
**Visit our website at [https://nightwolf.dev](https://nightwolf.dev) and follow us on [Twitter](https://twitter.com/nightwolfdev)!**