3

I have two input elements that are shown under *ngIf conditions.

<input type="text" id="textInput" *ngIf="showTextInput">
<input type="number" id="numericInput" *ngIf="showNumericInput">

<button (click)="editButtonClicked($event)">

Clicking on the button should set focus to the appropriate input element.

editButtonClicked(event) {
  // Focus on either #textInput or #numericInput element
}

I've looked into ElementRef to give the html input elements tags like #textInput and then define them on the class for example:

@ViewChild('textInput') textInput: ElementRef;

...but apparently this does not work on elements that have *ngIf conditionals.

How can I focus on an input element, onClick of a button?

bruh
  • 2,205
  • 7
  • 30
  • 42

3 Answers3

8

You could implement a super simple directive and have the desired effect.

html

<input type="text" autoFocus *ngIf="isInputVisible">

directive

import { Directive, ElementRef, OnInit } from "@angular/core";

@Directive({
  selector: "[autoFocus]"
})
export class AutoFocusDirective implements OnInit {
  private inputElement: HTMLElement;

  constructor(private elementRef: ElementRef) {
    this.inputElement = this.elementRef.nativeElement;
  }

  ngOnInit(): void {
    this.inputElement.focus();
  }
}

Working Demo:

https://stackblitz.com/edit/angular-ivy-vvgcch?file=src%2Fapp%2Fdirectives%2Fauto-focus.directive.ts

Lucas_Nt
  • 116
  • 1
  • 7
1

Yes @ViewChild will not work for elements who are under the control of a structural directive. There are two workaround that you can apply:

  1. Remove the *ngIf directive and hide the element using CSS style: 'display:none'.

  2. Select the element from the DOM using vanilla Javascript document.getElementById('someId'); and then focus the element.

I will prefer point 1.

Kushagra Saxena
  • 671
  • 5
  • 17
1

you can also do this by template reference variable if that's what you are looking for

in html

<input #text type="text" id="textInput">
<input #number type="number" id="numericInput">

<button (click)="editButtonClicked($event, text, number)"> Click </button>

in ts

editButtonClicked(e, text, number){
    if(text.value) {
      text.focus()
    } else {
      number.focus()
    }
  }
usman saleem
  • 150
  • 1
  • 17
  • Usman, as the input is under a *ngIf, you need change the value of the variable and, in a setTimeout make the focus -it's necesary the setTimeout to give time to Angular to show the element- – Eliseo Jun 24 '19 at 06:42
  • Thanks for your response usman, as Eliseo mentioned - due to the `*ngIf` conditional, this solution would require something like a setTimeout. I consider `setTimeout()` to be a rather hacky solution, so I will avoid that. – bruh Jun 24 '19 at 07:44