我可以在 Angular / Angular Material 中以编程方式移动 mat-horizontal-stepper 的步骤吗
Posted
技术标签:
【中文标题】我可以在 Angular / Angular Material 中以编程方式移动 mat-horizontal-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>
现在我想知道是否可以从每个步骤中删除按钮并将它们放在 <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>
【问题讨论】:
【参考方案1】:是的。可以使用MatStepper
的selectedIndex
属性跳转到特定的步进器。此外,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
您可以使用以下方法启用/禁用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>
【讨论】:
我只是在看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
:<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;
然后为名为@987654333@的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-horizontal-stepper 的步骤吗的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot 中将 Angular 环境变量传递给编译的静态 Angular 文件
如何在 Electron-Angular 项目中使用永远的监视器?