Установить фокус на элемент <input>

Я работаю с интерфейсным приложением с Angular 5, и мне нужно скрыть окно поиска, но при нажатии кнопки окно поиска должно отображаться и фокусироваться.

Я пробовал несколько способов, найденных в StackOverflow с директивой или около того, но не смог добиться успеха.

Вот пример кода:

@Component({
   selector: 'my-app',
   template: '
    <div>
    <h2>Hello</h2>
    </div>
    <button (click) ="showSearch()">Show Search</button>
    <p></p>
    <form>
      <div >
        <input *ngIf="show" #search type="text"  />            
      </div>
    </form>
    ',
  })
  export class App implements AfterViewInit {
  @ViewChild('search') searchElement: ElementRef;

  show: false;
  name:string;
  constructor() {    
  }

  showSearch(){
    this.show = !this.show;    
    this.searchElement.nativeElement.focus();
    alert("focus");
  }

  ngAfterViewInit() {
    this.firstNameElement.nativeElement.focus();
  }

Поле поиска не сфокусировано.

Как я могу это сделать?

Ответ 1

Измените метод поиска, как показано ниже.

showSearch(){
  this.show = !this.show;  
  setTimeout(()=>{ // this will make the execution after the above boolean has changed
    this.searchElement.nativeElement.focus();
  },0);  
}

Ответ 2

Вы должны использовать HTML автофокус для этого:

<input *ngIf="show" #search type="text" autofocus /> 

Примечание. Если ваш компонент сохраняется и используется повторно, он будет автоматически фокусироваться только при первом создании фрагмента. Это может быть преодолено с помощью глобального слушателя dom, который проверяет наличие атрибута автофокуса внутри фрагмента dom, когда он присоединен, и затем повторно применяет его или фокусируется с помощью javascript.

Ответ 3

Эта директива мгновенно сфокусируется и выбирает любой текст в элементе сразу после его отображения. Для некоторых случаев это может потребовать setTimeout, оно не было проверено.

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

@Directive({
  selector: '[appPrefixFocusAndSelect]',
})
export class FocusOnShowDirective implements OnInit {

  constructor(private el: ElementRef) {
    if (!el.nativeElement['focus']) {
      throw new Error('Element does not accept focus.');
    }
  }

  ngOnInit(): void {
    const input: HTMLInputElement = this.el.nativeElement as HTMLInputElement;
    input.focus();
    input.select();
  }
}

И в HTML:

 <mat-form-field>
     <input matInput type="text" appPrefixFocusAndSelect [value]="'etc'">
 </mat-form-field>

Ответ 4

Я собираюсь взвесить это (Angular 7 Solution)

input [appFocus] = "focus"....

import {AfterViewInit, Directive, ElementRef, Input,} from '@angular/core';

@Directive({
  selector: 'input[appFocus]',
})
export class FocusDirective implements AfterViewInit {

  @Input('appFocus')
  private focused: boolean = false;

  constructor(public element: ElementRef<HTMLElement>) {
  }

  ngAfterViewInit(): void {
    // ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
    if (this.focused) {
      setTimeout(() => this.element.nativeElement.focus(), 0);
    }
  }
}

Ответ 5

Чтобы выполнить выполнение после изменения логического значения и избежать использования тайм-аута, вы можете сделать:

import { ChangeDetectorRef } from '@angular/core';

constructor(private cd: ChangeDetectorRef) {}

showSearch(){
  this.show = !this.show;  
  this.cd.detectChanges();
  this.searchElement.nativeElement.focus();
}