如何使用 ngIf 将输入的焦点放在表单字段中

How to put the focus of an input in a form-field with ngIf

我遇到了一个问题,我想在我的代码中将重点放在条件输入上 基于可观察的数据。在我的示例中,我只是在 ngOnInit().

中将布尔值设置为 true
export class InputOverviewExample implements OnInit {
  bool: boolean;

  @ViewChild("input1", { static: true }) input1: MatInput;
  @ViewChild("input2", { static: true }) input2: MatInput;

  ngOnInit() {
    this.bool = true;
    this.input1.nativeElement.focus();
    this.input2.nativeElement.focus();
  }
}

而且我注意到当 mat-form-field 处于调节状态时焦点不起作用。

<form class="example-form">
  <h3>Without *ngIf :</h3>
  <mat-form-field appearance="outline" class="example-full-width">
    <input matInput #input1 placeholder="Auto focus" value="Test_input1" />
  </mat-form-field>

  <h3>With *ngIf :</h3>
  <mat-form-field appearance="outline" class="example-full-width" *ngIf="bool">
    <input matInput #input2 placeholder="Auto focus" value="Test_input2" />
  </mat-form-field>
</form>

StackBlitz link

有人会解决这个问题

谢谢

ngOnInit() {
    this.bool = true;
    if(...){
        this.input1.nativeElement.focus();
    }
    else{
        this.input2.nativeElement.focus();
    }
    
}

您需要了解 ViewChild {static:true} 和 {static:false} 以及 {read}

所以,首先将您的 ViewChild 定义为

@ViewChild("input1", { static: false,read:ElementRef }) input1: ElementRef;
@ViewChild("input2", { static: false,read:ElementRef }) input2: ElementRef;

static:false 使得 Angular 检查是否在 *ngIf

read:ElementRef 使您的“input1”和“input2”被视为 ElementRef,而不是 MatInput

您需要的第二件事是 Angular 的工作原理。 Angular 执行所有操作并刷新应用程序,所以如果你写

this.bool = true;
this.input2.nativeElement.focus(); //<--this.input2 is undefined

this.input2 是未定义的,因为 Angular 没有重新绘制应用程序,所以你需要用 setTimeout 括起来 - 你可以像对 Angular 说的那样考虑 setTimeout “嘿,不要忘记刷新应用程序后,您需要将其设为另一个指令”- 或使用 ChangeDetectorRef.

所以

  ngOnInit() {
    this.bool = true;
    setTimeout(()=>{
      this.input1.nativeElement.focus();
      this.input2.nativeElement.focus();
    })
  }

使用QueryList查询元素

import { Component, OnInit, ViewChild,   
QueryList,
  ViewChildren, ElementRef, AfterViewInit, ChangeDetectorRef } from "@angular/core";
import { MatInput } from "@angular/material";
import {startWith} from 'rxjs/operators';

/**
 * @title Basic Inputs
 */
@Component({
  selector: "input-overview-example",
  styleUrls: ["input-overview-example.css"],
  templateUrl: "input-overview-example.html"
})
export class InputOverviewExample implements OnInit, AfterViewInit {
  bool: boolean;
  @ViewChild("input1", { static: true }) input1: MatInput;
  // @ViewChild("input2", { static: true }) input2: MatInput;
  @ViewChildren('input2') input2: QueryList<ElementRef>;

constructor(private cd: ChangeDetectorRef) {

}
  ngOnInit() {
    this.bool = true;
    this.input1.nativeElement.focus();
  }

  ngAfterViewInit(): void {
     this.input2.changes
     .pipe(
        startWith(true),
      )
      .subscribe(() => {
        this.input2.forEach((elementRef: ElementRef) => {
          if(elementRef) {
             elementRef.nativeElement.focus();
             this.cd.detectChanges();
          }
        });
      });
  }
}

DEMO