Auto-focusing an Angular Input — The Easy Way? (Part 2 — Directives)
By: David Mcintosh
Tags: Angular, Software Development, Coding, Directives, Angular Cli

There’s more than one way to skin a cat. While not the best metaphor, admittedly, it always holds true in programming. Don’t worry, though, this isn’t a disgusting article about cat-skinning methods and which are best. It’s a disgusting article showcasing another, more “Angular” way to set auto-focus on input fields throughout your Angular application.

First thing’s first, you’ll want to fire up a new Angular application.

ng new angular-directive

Next, we’ll be creating an Angular Directive. A directive, or attribute directive, changes the appearance or behavior of a DOM element. There are 3 kinds of directives: Components, Structural and Attribute directives. In our case, we’ll be setting focus on an element, so that’s an attribute directive. Using NgIf or NgFor to render elements is an example of Structural elements (Read more).

Before creating our directive, add the following VSCode extension: Angular Schematics. As of writing this, the current version is 4.5.0, but it shouldn’t make much of a difference.

Now, right-click on our “app” folder and select the option “Angular: Generate another schematic”. Then, choose “directive” as the type of schematics you wish to generate. For simplicity sake, name it “autofocus”. Click Enter, then Confirm.

You should see 2 new files in the app directory:

autofocus.directive.spec.ts autofocus.directive.ts

Open the autofocus.directive.ts file and let’s code our directive!

We’ll need an input, so within the Class, just before the constructor, add the following:

@Input() public autoFocus: boolean;

Next, we’ll inject an ElementRef into our constructor. This is so we can have a reference to the input field(s) that we’ll use our directive on. Your constructor should look like this:

constructor(private el: ElementRef) { }

To actually set focus on the element, we’ll use Angular’s ngAfterContentInit. This is a lifecycle event that is called after a directive’s content has been fully initialized.

We need to have our class implement this, like so:

export class AutofocusDirective implements AfterContentInit

Lastly, we’ll code our ngAfterContentInit logic, which is a setTimeout function that runs every 500 milliseconds and tries to set focus onto the element. This is because we need to give Angular time to draw the element onto the screen before we can set focus.

public ngAfterContentInit(): void { setTimeout( () => { this.el.nativeElement.focus(); }, 500) }

The entire file should look like this:

Angular autofocus Directive

To use the directive, we’ll go to our app.component.html file and clear the contents. Next, add a basic input field and use the selector for our autofocus directive, which is “appAutoFocus”, as seen above:

Autofocused! <input appAutoFocus>

If you serve your application, when it loads, the input field should be auto-focused.

ng serve --open

We can even test a scenario whereby the input field is not drawn/rendered immediately, but when a button is clicked. To do that, replace the contents of your app.component.html file with the following:

<div class="content center"> <br> <br> <button (click)="showInput()">Show/Hide</button> 🧐 <br> <br> <div *ngIf="showInputField"> Autofocused! <input appAutoFocus> 🎉 </div> </div>

Now we have a button that either shows or hide the input field. When it is shown, it should be auto-focused.

Add the following to your app.component.ts file for it to show/hide the :

showInputField: boolean = false; showInput() { this.showInputField = !this.showInputField; }

Side Note:

After creating the directive, and coding its logic, you may get an error in your .spec file. This error is just because you need to create a mock element in it for testing purposes, but it should not affect your ability to serve the app. If it does both you, replace the line with the definition of the directive with this in your spec file: