Angular Material 将初始焦点设置为表单控件,无需单击事件

Jen*_*r S 2 typescript angular-material angular angular-reactive-forms

我正在使用 Angular 9 和 Material。我有一个步进器,它将引导用户完成我们的工作流程的步骤。

我需要用户能够完全使用键盘完成这些步骤,而无需单击控件。我见过很多通过单击事件将焦点设置在控件上的示例。我不希望用户必须单击按钮才能将焦点设置在第一个文本区域。 当步进器初始化时,如何才能获得文本区域的初始焦点,而无需用户单击任何内容? 我尝试在 ngAfterViewInit 中使用元素引用,但它不起作用。谁能帮助我理解如何做到这一点?谢谢。

这是我的 HTML:

<pseudo-common-tool-header title="{{this.title}}"></pseudo-common-tool-header>
<div class="pseudo-content-manager-tool-area">
<mat-horizontal-stepper #stepper>
<mat-step [stepControl]="formGroup">
    <form [formGroup]="formGroup">
        <ng-template matStepLabel>Workstation Ids</ng-template>
        <div>
            <mat-form-field appearance="outline" class="eris-width-45" >
            <mat-label>List of Old/New Workstations to swap (one pair per line)</mat-label>
            <textarea #wkstns rows="8" #workstations matInput placeholder="Old Workstation, New Workstation" formControlName="workstations" required></textarea>
            </mat-form-field>
        </div>
        <div>
            <mat-form-field appearance="outline" >
                <mat-label>Soft Delete Date</mat-label>
                <input matInput #softDate [min]="minDate" [matDatepicker]="picker3" formControlName="removalDate">
                        <mat-datepicker-toggle matSuffix [for]="picker3"></mat-datepicker-toggle>
                        <mat-datepicker #picker3 color="primary"></mat-datepicker>
            </mat-form-field>
        </div>
        <div>
            <button color="primary" #step1next mat-raised-button matStepperNext>Next</button>
        </div>
    </form>
</mat-step>
<mat-step  label="Validate">
    <div>
        <button mat-raised-button color="secondary" matStepperPrevious>Back</button>
        <button mat-raised-button color="secondary" matStepperNext>Next</button>
      </div>
</mat-step>
<mat-step>
    <ng-template matStepLabel>Epic Build</ng-template>
</mat-step>
Run Code Online (Sandbox Code Playgroud)

这是我的组件:

@Component({
 templateUrl: './swap-workstations.component.html',
 styleUrls: ['./swap-workstations.component.scss']
  })

 @PseudoTool({
 title: 'Check Workstation Existence in Epic',
 componentName: 'CheckWorkstationExistenceInEpicComponent'
  })

  export class SwapWorkstationsComponent extends BasePseudoTool implements OnInit {
       formGroup: FormGroup;
    // minimum date for date picker
    minDate: Date;
 @ViewChild('wkstns') wkstns: ElementRef;
 @ViewChild('softDate') softDate: ElementRef;
 @ViewChild('step1next') step1next: ElementRef;

 constructor(private formBuilder: FormBuilder) {
     super();
    }

 ngOnInit(): void {
   this.formGroup = this.formBuilder.group({
     workstations: ['', Validators.required],
     removalDate: ['', Validators.required]
   });

// Set minimum date for date pickers.
this.minDate = new Date();
 }

 ngViewAfterInit(): void {
   this.wkstns.nativeElement.focus();
 }   
Run Code Online (Sandbox Code Playgroud)

}

小智 6

理想情况下,您会使用该autofocus属性,但它很不稳定并且并不总是有效,因此我只是创建一个指令来确保它有效。我在表单上使用它来将焦点设置在第一个元素上,以便用户可以使用键盘导航表单。

import { coerceBooleanProperty } from "@angular/cdk/coercion";
import { DOCUMENT } from "@angular/common";
import {
  AfterViewInit,
  Directive,
  ElementRef,
  Inject,
  Input
} from "@angular/core";

@Directive({
  selector: "[autofocus]"
})
export class AutofocusDirective implements AfterViewInit {
  private _host: HTMLElement;
  private _focused: Element | null;
  private _autofocus = true;

  @Input()
  set autofocus(value: boolean | string) {
    this._autofocus = coerceBooleanProperty(value);
  }

  constructor(
    private readonly element: ElementRef,
    @Inject(DOCUMENT) document: HTMLDocument
  ) {
    if (typeof this.element.nativeElement.focus !== "function") {
      throw new Error("Html element must be focusable");
    }
    this._host = element.nativeElement;
    this._focused = document.activeElement;
  }

  public ngAfterViewInit(): void {
    if (this._autofocus && this._host && this._host !== this._focused) {
      setTimeout(() => this.element.nativeElement.focus());
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以将该autofocus属性添加到文本区域。这样可以使您的组件保持清洁并且可以重复使用。