【问题标题】:Focus input after going to the next step in MatStepper在 MatStepper 中进行下一步后的焦点输入
【发布时间】:2018-02-27 15:00:10
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: angular angular-material2


    【解决方案1】:

    您使用选择更改事件走在正确的道路上。 查看分叉的 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>
    

    然后通过使用选择(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();
      }
    }
    

    【讨论】:

      【解决方案2】:

      我已经创建了自己的替代版本,以替代 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 仍然会很好。

      【讨论】:

        【解决方案3】:

        具有输入 ID 和 selectionChange 侦听器的解决方案有效,您还可以添加 (animationDone) 侦听器,这样您就可以在没有 setTimeout() 逻辑的情况下调用 setFocus()。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-03
          • 1970-01-01
          • 2017-02-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多