进入MatStepper的下一步后,重点输入

时间:2018-02-27 15:00:10

标签: angular angular-material2

如何在步骤1中单击“下一步”按钮后以编程方式将焦点设置为“地址”输入,因此在执行步骤1(“填写您的姓名”)后执行步骤2(“填写您的地址”)。

https://stackblitz.com/angular/onnbkqrydrg?file=app%2Fstepper-overview-example.ts https://material.angular.io/components/stepper/overview

enter image description here

enter image description here

这就是我想要实现的目标:

enter image description here

我已经在尝试使用MatStepper的selectionChange事件,但它似乎在步骤2可见之前被触发,所以它不起作用。

3 个答案:

答案 0 :(得分:3)

您使用选择更改事件在正确的路径上。 请参阅forked StackBlitz:

StackBlitz

您要做的是为您的输入元素分配一个id,可用于与步进器的选定索引相关联,例如:

<mat-step [stepControl]="firstFormGroup">
    <form [formGroup]="firstFormGroup">
      <ng-template matStepLabel>Fill out your name</ng-template>
      <mat-form-field>
        <input id="input0" matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
      </mat-form-field>
      <div>
        <button mat-button matStepperNext>Next</button>
      </div>
    </form>
  </mat-step>
  <mat-step [stepControl]="secondFormGroup">
    <form [formGroup]="secondFormGroup">
      <ng-template matStepLabel>Fill out your address</ng-template>
      <mat-form-field>
        <input  id="input1" matInput placeholder="Address" formControlName="secondCtrl" required>
      </mat-form-field>
      <div>
        <button mat-button matStepperPrevious>Back</button>
        <button mat-button matStepperNext>Next</button>
      </div>
    </form>
  </mat-step>

然后通过使用selection(selectionChange)事件,您可以在等待它显示在DOM中之后将焦点设置在输入元素上:

export class StepperOverviewExample implements AfterViewInit {
  isLinear = false;
  firstFormGroup: FormGroup;
  secondFormGroup: FormGroup;

  public targetInput = 'input0';

  constructor(private _formBuilder: FormBuilder) { }

  ngOnInit() {
    this.firstFormGroup = this._formBuilder.group({
      firstCtrl: ['', Validators.required]
    });
    this.secondFormGroup = this._formBuilder.group({
      secondCtrl: ['', Validators.required]
    });
  }

  ngAfterViewInit() {
    this.setFocus();
  }

  private setFocus() {
    let targetElem = document.getElementById(this.targetInput);
    setTimeout(function waitTargetElem() {
      if (document.body.contains(targetElem)) {
        targetElem.focus();
      } else {
        setTimeout(waitTargetElem, 100);
      }
    }, 100);
  }

  onChange(event: any) {
    let index = String(event.selectedIndex);
    this.targetInput = 'input' + index;
    this.setFocus();
  }
}

答案 1 :(得分:0)

我已经为Narm提出的版本创建了自己的替代版本。我遇到的问题是渲染实际步进器被推迟了(例如,从服务器加载数据)ngAfterViewInit触发得太早了。为了解决这个问题,我在完成步骤动画后设置焦点。它会产生轻微的延迟,但允许组件稳定下来。 StackBlitz和代码:

export class StepperOverviewExample implements OnInit {
  isLinear = false;
  firstFormGroup: FormGroup;
  secondFormGroup: FormGroup;
  private targetId = 'input0';

  constructor(private _formBuilder: FormBuilder) {}

  ngOnInit() {
    this.firstFormGroup = this._formBuilder.group({
      firstCtrl: ['', Validators.required]
    });
    this.secondFormGroup = this._formBuilder.group({
      secondCtrl: ['', Validators.required]
    });
  }

  setFocus() {
    const targetElem = document.getElementById(this.targetId);
    targetElem.focus();
  }

  setTargetId(event: any) {
    this.targetId = `input${event.selectedIndex}`;
  }
}
<mat-horizontal-stepper  (animationDone)="setFocus()" (selectionChange)="setTargetId($event)" [linear]="isLinear" #stepper>
  <mat-step [stepControl]="firstFormGroup">
    <form [formGroup]="firstFormGroup">
      <ng-template matStepLabel>Fill out your name</ng-template>
      <mat-form-field>
        <input id="input0" matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
      </mat-form-field>
      <div>
        <button mat-button matStepperNext>Next</button>
      </div>
    </form>
  </mat-step>
  <mat-step [stepControl]="secondFormGroup">
    <form [formGroup]="secondFormGroup">
      <ng-template matStepLabel>Fill out your address</ng-template>
      <mat-form-field>
        <input id="input1" matInput placeholder="Address" formControlName="secondCtrl" required>
      </mat-form-field>
      <div>
        <button mat-button matStepperPrevious>Back</button>
        <button mat-button matStepperNext>Next</button>
      </div>
    </form>
  </mat-step>
  <mat-step>
    <ng-template matStepLabel>Done</ng-template>
    You are now done.
    <div>
      <button mat-button matStepperPrevious>Back</button>
      <button mat-button (click)="stepper.reset()">Reset</button>
    </div>
  </mat-step>
</mat-horizontal-stepper>

我认为摆脱document以获得服务器端渲染兼容性仍然会很好。

答案 2 :(得分:0)

具有输入id和selectionChange侦听器的解决方案可以工作,您还可以添加(animationDone)侦听器,以便无需setTimeout()逻辑即可调用setFocus()。