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

Posted

技术标签:

【中文标题】我可以在 Angular / Angular Material 中以编程方式移动 mat-h​​orizo​​ntal-stepper 的步骤吗【英文标题】:Can I programmatically move the steps of a mat-horizontal-stepper in Angular / Angular Material 【发布时间】:2018-03-10 04:51:36 【问题描述】:

我有一个关于 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>

现在我想知道是否可以从每个步骤中删除按钮并将它们放在 &lt;mat-horizontal-stepper&gt; 的其他位置的静态位置,甚至在 &lt;mat-horizontal-stepper&gt; 之外,我可以使用我的代码中的代码来回导航组件打字稿文件。给出一个想法,我希望我的 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>

【问题讨论】:

【参考方案1】:

是的。可以使用MatStepperselectedIndex 属性跳转到特定的步进器。此外,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 demo


您还可以使用ViewChild 来获取对 TypeScript 中步进器组件的引用,如下所示:

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

goBack()
    this.myStepper.previous();


goForward()
    this.myStepper.next();

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


您可以使用以下方法启用/禁用BackNext 按钮:

<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>

【讨论】:

我只是在看ViewChild,看看我如何引用步进器——但你已经打败了我!喜欢您也添加了禁用/启用功能的事实!给点分数吧! ViewChild 也是获取步进器的好选择。但我更喜欢传递一个id。我还在演示中添加了ViewChild 解决方案\o/ 嗨 Faisal 感谢您提供如此好的答案,还有一个帮助,我们可以传递角度组件,而不是传递表单到 mat-step,然后根据该组件是否有效,我可以遍历到下一个 mat -step,如何实现,谢谢 不错的解决方案。但是我们怎么能将滚动区域限制为步进器的内容而不是实际的标题。如果您添加大量内容,则标题将滚动到视线之外。由于标题指示了用户在某个进程中的位置,因此无论每个步骤中的内容量如何,标题都可见是很重要的。 如果你使用 Angular 8,并且使用 @ViewChild,你应该使用 static: false @ViewChild('stepper', static: false) private myStepper: MatStepper; Per Angular,这个值将默认为 false i> 在 Angular 9+ link【参考方案2】:

除了@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 demo。

【讨论】:

【参考方案3】:

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

像这样创建stepper&lt;mat-horizontal-stepper linear #matHorizontalStepper&gt;

像这样定义mat-step&lt;mat-step [completed]="isThisStepDone"&gt;

mat-step 内部创建一个按钮以进入下一步,如下所示:&lt;button (click)="next(matHorizontalStepper)"&gt;NEXT STEP&lt;/button&gt;

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

另外,在.ts 文件中将isThisStepDone 初始化为falseisThisStepDone: boolean = false;

然后为名为@9​​87654333@的NEXT STEP按钮编写方法:

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

注意:异步部分 (setTimeout()) 是必需的,因为通过 isThisStepDone 进行状态传播。

【讨论】:

由于通过isThisStepDone 进行状态传播,因此需要异步部分 (setTimeout())。 Thnks bruh,这就是我一直在寻找的……对于线性步进器。【参考方案4】:

您也可以通过使用 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;
  

【讨论】:

我只是在我的函数中使用@ViewChild('stepper') private myStepper: MatStepper; 而不是this.matStepper.next();。完美运行【参考方案5】:

如果你在子组件内部,你可以注入步进器。

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();

【讨论】:

以上是关于我可以在 Angular / Angular Material 中以编程方式移动 mat-h​​orizo​​ntal-stepper 的步骤吗的主要内容,如果未能解决你的问题,请参考以下文章

Angular 12 日期选择器

在 Spring Boot 中将 Angular 环境变量传递给编译的静态 Angular 文件

Angular 5 ng-repeat 实现

如何在 Electron-Angular 项目中使用永远的监视器?

如何在 Jhipster (spring boot + angular) 应用程序上设置上下文路径

在 Angular 5 中禁用 zone.js 后,ngOnInit 未触发