我有一个关于 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>
是的。可以使用
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>
除了 @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 演示。
如果您想要以编程方式导航到下一步,并且如果您使用线性步进器,请按照以下步骤操作:
创建一个
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()
) 是必需的。
如果您位于子组件内部,则可以注入步进器。
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();
}
您还可以通过使用 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;
}
}
我实现的解决方案允许前面的步骤验证(它填充了验证点):
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;
});
}
}
如果您想知道当前选择了哪个步骤,并且仅在用户不存在时才移至另一个步骤,还有另一种解决方案。
为 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();
}
}
您可以在 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>