角材料步进器在选择更改之前并防止在某些条件下进行步进更改
Posted
技术标签:
【中文标题】角材料步进器在选择更改之前并防止在某些条件下进行步进更改【英文标题】:Angular material stepper before-selection-change & prevent step-change for some condition 【发布时间】:2019-08-25 03:22:51 【问题描述】:我正在使用线性垫步进器。
它与下一个工作正常。我做 api 调用 & 如果它成功然后我调用 stepper-next 事件而不是使用 matStepperNext 指令。
现在,当用户在第 1 步填写所有数据并直接单击其他一些 header 的下一步(或任何其他编辑记录模式)上的步骤时,它将由于表单有效,因此重定向到下一步。
我想在此之前进行服务调用和在服务调用成功之前阻止步骤更改然后它应该重定向到下一步,否则它不应该。
我在 doc 中找不到任何实现此功能的方法。
任何人都可以建议我做什么。我不想禁用标题点击。
【问题讨论】:
【参考方案1】:以下方法对我有用:
-
使 mat-stepper 线性化
<mat-vertical-stepper [linear]="true" #stepper>
....
</mat-vertical-stepper>
-
使步骤不可编辑,不可选择,并将 stepControl 与 FormGroup 相关联
<mat-step [editable]="false" [optional]="false" [stepControl]="desiredServiceFormGroup">
<form [formGroup]="desiredServiceFormGroup">
...
</form>
</mat-step>
-
为您在 html 中描述的表单项向您的 FormGroup 添加控件,并添加一个额外的控件。对于您的 html 代码中不存在的表单控件(在此示例中,我添加了名为“x”的控件,在我的 html 代码中不存在)
ngOnInit()
this.desiredServiceFormGroup = this.formBuilder.group(
desiredTarget: [ '', Validators.required],
paymentAgreed: ['', Validators.required],
...
x: ['', Validators.required]
);
使用这个额外的验证器,您的 stepControl 将始终为 false。 当 stepControl 为 false 时,step 不是可选的,不可编辑且 stepper 是线性的。直接单击步骤标题不会更改当前步骤。
-
button 不会与 formControl 关联(在这种情况下,它将始终被禁用)。就我而言,我手动验证每个表单项
<button [disabled]="desiredTarget == null || !paymentAgreed" (click)="createVerification(desiredTarget.targetId, stepper)">NEXT</button>
-
进行所需的操作,完成后,删除使表单控件始终无效的额外控件。以编程方式进入下一步。
async createVerification(targetId: number, stepper?: MatStepper)
this.verification = await this.dataService.createVerification(targetId);
if (stepper !== undefined)
this.desiredServiceFormGroup.removeControl('x');
stepper.next();
-
如果您需要重置步进器,请将额外的控件添加到 FormControl
reset(stepper?: MatStepper)
this.desiredServiceFormGroup.addControl('x', new FormControl('', [Validators.required]));
stepper.reset();
【讨论】:
【参考方案2】:您可以通过以下方式对此进行完全控制。证明,工作。对于"@angular/cdk": "8.2.3"
,我不确定未来的版本,也许他们有一些内置功能。
简答:
在页面上呈现步进器组件后。您应该循环遍历步进器的所有步骤,并使用您自己的版本覆盖每个步骤的内置 select()
方法。
您将在自己的版本中做什么?
做一些计算 拨打服务电话 随心所欲 如果您希望用户进入新步骤,请更改currentStepIndex
长答案:
HTML:
<mat-horizontal-stepper [selectedIndex]="selectedStepIndex" #stepper>
在控制器中:
@ViewChild('stepper', static: false ) stepper: MatStepper;
在页面上呈现步进器后,您可以像这样覆盖 select
方法:
// I personally do this in ngAfterViewInit() method
setTimeout(() =>
this.stepper.steps.forEach((step, idx) =>
step.select = () =>
// Your custom code here
// if you want to change step do execute code below
this.selectedStepIndex = idx;
;
);
);
【讨论】:
【参考方案3】:这里是基于 Sam Tsai 的回答的工作建议,这是我找到的最好的。我只是使用“step”值是代码,并且只有普通的导航按钮。
只有如果你有正确的按钮,你可以返回和前进(我的意思是,这不可能通过单击步骤来更改步骤)。这意味着您完成了第一步,然后是第二步,依此类推。
工作示例在这里: https://stackblitz.com/edit/angular-tznwxe
诀窍是调用goStep(x)
,其中x
是从1 开始的步骤。您可以通过添加goNext()
和goPrevious()
来增强它,这很简单。
请注意,步进器的“selectedIndex”必须更改为setTimeout()
:这是此处讨论的已知错误:https://github.com/angular/components/issues/8479#issuecomment-444063732
【讨论】:
【参考方案4】:您可以尝试在mat-step
上利用editable
和completed
属性。
见https://material.angular.io/components/stepper/overview#editable-step
没有示例,一种解决方案是:
-
在进行服务调用时将所有其他步骤的
editable
属性设置为false
跟踪对mat-step
的点击并保留此值,以便您知道用户打算去哪里
在服务调用成功或失败时将editable
属性设置为true
(取决于您要如何处理错误)
以编程方式转到 #2 中跟踪的步骤
【讨论】:
从哪个事件我可以做到这一点。当我单击步骤标题时,它将重定向到该步骤。 对,我误解了你的问题。此时,您可以尝试禁用我不喜欢的pointer-events
(请参阅***.com/questions/46933953/…)或通过ng-template
执行自定义步骤标签并使其覆盖整个标题空间(这也是一个黑客),请参阅stackblitz.com/angular/jbbpbonlbpe【参考方案5】:
您可以使用完成的输入装饰(布尔),如果步骤1被标记为完成则将转到步骤2。
一旦您的服务调用完成,您可以将完成标记为“true”,然后它将 转到第2步,否则它将停留在当前步骤。
参考:https://stackblitz.com/edit/angular-mat-stepper-demo-with-selection-change?file=src%2Fapp%2Fapp.component.html
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于角材料步进器在选择更改之前并防止在某些条件下进行步进更改的主要内容,如果未能解决你的问题,请参考以下文章