我可以在 Angular / Angular Material 中以编程方式移动 mat-horizontal-stepper 的步骤吗

问题描述 投票:0回答:8

我有一个关于 Angular Material(Angular 4+)的问题。假设在我的组件模板中我添加了一个

<mat-horizontal-stepper>
组件,并且在每个步骤
<mat-step>
中我都有步进器按钮来导航该组件。就像这样...

<mat-horizontal-stepper>
  <mat-step>
    Step 1
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
  <mat-step>
    Step 2
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
  <mat-step>
    Step 3
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
</mat-horizontal-stepper>

现在我想知道是否可以将按钮从每个步骤中删除,并将它们放在

<mat-horizontal-stepper>
中其他位置的静态位置,甚至位于
<mat-horizontal-stepper>
之外,并且我可以使用组件打字稿中的代码来前后导航文件。为了给出一个想法,我希望我的 HTML 是这样的

<mat-horizontal-stepper>
    <mat-step>
        Step 1
    </mat-step>
    <mat-step>
        Step 2
    </mat-step>
    <mat-step>
        Step 3
    </mat-step>
    <!-- one option -->
    <div>
       <button mat-button matStepperPrevious type="button">Back</button>
       <button mat-button matStepperNext type="button">Next</button>
    </div>
</mat-horizontal-stepper>

<!-- second option -->
<div>
   <button (click)="goBack()" type="button">Back</button>
   <button (click)="goForward()" type="button">Next</button>
</div>
angular angular-material angular-material2
8个回答
275
投票

是的。可以使用

selectedIndex
MatStepper
属性跳转到特定步进器。此外,
MatStepper
公开了公共方法
next()
previous()
。您可以使用它们来回移动。

在您的模板中:

为您的步进器添加一个 id,例如

#stepper
。然后在您的
goBack()
goForward()
方法中,传递步进器 id:

<mat-horizontal-stepper #stepper>
    <!-- Steps -->
</mat-horizontal-stepper>    
<!-- second option -->
<div>
   <button (click)="goBack(stepper)" type="button">Back</button>
   <button (click)="goForward(stepper)" type="button">Next</button>
</div>

..在你的打字稿中:

import { MatStepper } from '@angular/material/stepper';

goBack(stepper: MatStepper){
    stepper.previous();
}

goForward(stepper: MatStepper){
    stepper.next();
}

链接到stackblitz 演示


您还可以使用

ViewChild
获取对 TypeScript 中步进器组件的引用,如下所示:

@ViewChild('stepper') private myStepper: MatStepper;

goBack(){
    this.myStepper.previous();
}

goForward(){
    this.myStepper.next();
}

在这种情况下,您不必在组件 html 的方法中传递步进器引用。链接到 使用 ViewChild 的演示


您可以使用以下方法启用/禁用

Back
Next
按钮:

<button (click)="goBack(stepper)" type="button" 
        [disabled]="stepper.selectedIndex === 0">Back</button>
<button (click)="goForward(stepper)" type="button" 
        [disabled]="stepper.selectedIndex === stepper._steps.length-1">Next</button>

47
投票

除了 @Faisal 的答案之外,这是我对使 MatStepper 跳转而无需在参数中传递步进器的看法。

当您需要更灵活地操作步进器时,例如,这会很有帮助。来自

Service
或其他东西。

HTML:

<div fxLayout="row" fxLayoutAlign="center center" fxLayoutGap="6px">
  <button (click)="move(0)">1st</button>
  <button (click)="move(1)">2nd</button>
  <button (click)="move(2)">3rd</button>
  <button (click)="move(3)">4th</button>
</div>

TS 文件:

move(index: number) {
    this.stepper.selectedIndex = index;
}

这是 stackblitz 演示


33
投票

如果您想要以编程方式导航到下一步,并且如果您使用线性步进器,请按照以下步骤操作:

  • 创建一个

    stepper
    ,如下所示:
    <mat-horizontal-stepper linear #matHorizontalStepper>

  • 像这样定义

    mat-step
    <mat-step [completed]="isThisStepDone">

  • 从内部

    mat-step
    创建一个按钮以转到下一步,如下所示:
    <button  (click)="next(matHorizontalStepper)">NEXT STEP</button>

  • .ts
    文件中声明一个名为
    stepper
    MatStepper 引用:
    @ViewChild('matHorizontalStepper') stepper: MatStepper;

  • 此外,在

    .ts
    文件中将
    isThisStepDone
    初始化为 false
    isThisStepDone: boolean = false;

  • 然后为名为 next()

    NEXT STEP
    按钮编写方法:

     submit(stepper: MatStepper) {
      this.isThisStepDone = true;
      setTimeout(() => {           // or do some API calls/ Async events
       stepper.next();
      }, 1);
     }
    

注意:由于通过 isThisStepDone 进行状态传播,异步部分 (

setTimeout()
) 是必需的


6
投票

如果您位于子组件内部,则可以注入步进器。

MyMainPageWithStepper.html (simplified)

<mat-horizontal-stepper>
  <mat-step label="Upload">
    <my-component></my-component>
  </mat-step>
</mat-horizontal-stepper>

MyComponent.ts

constructor(private readonly _stepper: CdkStepper}{}

someFunction(): void {
   this._stepper.next();
}

3
投票

您还可以通过使用 selectedIndex 指定步进器的实际索引来完成此操作。

堆栈闪电战: https://stackblitz.com/edit/angular-4rvy2s?file=app%2Fstepper-overview-example.ts

HTML:

<div class="fab-nav-container">
   <mat-vertical-stepper linear="false" #stepper>
       <mat-step *ngFor="let step of stepNodes; let i = index">
           <ng-template matStepLabel>
               <p> {{step.title}} </p>
           </ng-template>
       </mat-step>
   </mat-vertical-stepper>
</div>

<div class="button-container">
   <div class="button-grp">
      <button mat-stroked-button (click)="clickButton(1, stepper)">1</button>
      <button mat-stroked-button (click)="clickButton(2, stepper)">2</button>
      <button mat-stroked-button (click)="clickButton(3, stepper)">3</button>
   </div>
</div>

TS:

import {Component, OnInit, ViewChild} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import { MatVerticalStepper } from '@angular/material';
import { MatStepper } from '@angular/material';
export interface INodes {
    title: string;
    seq: number;
    flowId: string;
}
/**
 * @title Stepper overview
 */
@Component({
  selector: 'stepper-overview-example',
  templateUrl: 'stepper-overview-example.html',
  styleUrls: ['stepper-overview-example.scss'],
})
export class StepperOverviewExample implements OnInit {
  @ViewChild(MatVerticalStepper) vert_stepper: MatVerticalStepper;
  @ViewChild('stepper') private myStepper: MatStepper;

  stepNodes: INodes[] = [
    { title: 'Request Submission', seq: 1, flowId: 'xasd12'}, 
    { title: 'Department Approval', seq: 2, flowId: 'erda23'}, 
    { title: 'Requestor Confirmation', seq: 3, flowId: 'fsyq51'}, 
  ];

  ngOnInit() {
  }
  ngAfterViewInit() {
    this.vert_stepper._getIndicatorType = () => 'number';
  }
  clickButton(index: number, stepper: MatStepper) {
      stepper.selectedIndex = index - 1;
  }
}

1
投票

我实现的解决方案允许前面的步骤验证(它填充了验证点):

  ngAfterViewInit() {
        if(this.isDone) {
          this.stepper.selectedIndex = 0;
          this.stepper.linear = false;
    
          // remove the validation // which makes the next call to the next method validate the step. warning => the validation should be readded.
          this.firstFormGroup = this._formBuilder.group({
            email: ['',],
            password:['',]
          });
    
          this.stepper.next();
          
          this.secondFormGroup = this._formBuilder.group({
            pricingYear: ['',],
            pricingMontly: ['',],
          });
          this.stepper.next();
    
          setTimeout(() => {
            this.stepper.linear = true;
         });
        }
      }

0
投票

如果您想知道当前选择了哪个步骤,并且仅在用户不存在时才移至另一个步骤,还有另一种解决方案。

为 mat-step 设置 id

<mat-stepper #stepper>
 <mat-step id='product'></mat-step>
 <mat-step id='date'></mat-step>
 <mat-step id='info'></mat-step>
</mat-stepper>

现在在组件中,如果我们想进入“日期”步骤,我们可以执行以下操作:

  @ViewChild('stepper') stepper: MatStepper;
  goToDate() {
   const firstStepId = this.stepper.steps?.first?.content?.elementRef?.nativeElement?.parentElement?.id;
      if (firstStepId === 'product' && this.stepper.selectedIndex === 0) {
        this.stepper.next();
      }
  }

0
投票

您可以在 MatStepper 上使用 ViewChild

在 HTML 文件中:

<mat-horizontal-stepper #stepper class="transactions-stepper" (selectionChange)="changeStepper($event)">

并在 ts 文件上定义下一个和上一个方法

在 TS 文件中:

@ViewChild('stepper') private myStepper: MatStepper;

nextStep(): void {
   this.myStepper.next();
}

previousStep(): void {
   this.myStepper.previous();
}

您还可以通过组件上的输入将 viewChild 传递给步进器 您的子组件上的下一个或上一个

喜欢:

<transactions-list #transactionsList [stepper]="stepper"></transactions-list>
© www.soinside.com 2019 - 2024. All rights reserved.