Material Design - 步进器如何删除/禁用步骤?

时间:2017-10-12 12:55:03

标签: html angular angular-material2

我正在使用Material - Angular2 Stepper,我还有其他步骤要添加/启用,具体取决于用户在第一步中选择的内容。

我尝试了以下内容:
- 将其他表格加载到阵列中,
- 然后使用*ngFor

在模板中循环遍历它
<mat-vertical-stepper linear>
  <mat-step [stepControl]="firstForm" label="First">
    <!-- Some form controls -->
  </mat-step>
  <mat-step *ngFor="let f of additionalForms" [stepControl]="f.form"
      [label]="f.label">
    <!-- Additional Steps -->
  </mat-step>
</mat-vertical-stepper>

这适用于添加新步骤,问题是我无法删除它们。如果用户碰巧回到第一个表单并取消选中某些内容,则不需要这些额外的步骤。

所以尝试类似:this.additionalForms = []并不会删除这些步骤。 (直到您点击其中一个&#34;已移除的&#34;步骤,然后它会抛出错误:Cannot read property 'editable' of undefined,然后才会在视觉上删除它们

我也试过ChangeDetectorRef.detectChanges() 并尝试包装到NgZone.run()

但没有区别

任何解决方案吗?

5 个答案:

答案 0 :(得分:5)

所以我设法解决这个问题:
https://github.com/angular/material2/issues/7700#issuecomment-336138411

1)引用步进器:

<mat-vertical-stepper #stepper></mat-vertical-stepper>

2)然后,在.ts方面:

import { ViewChild } from '@angular/core';
import { MatVerticalStepper } from '@angular/material';

@ViewChild('stepper') stepper: MatVerticalStepper;

clearAdditionalForms(): void {
  this.inventoryForms = [];
  this.stepper._stateChanged(); // <- this : Marks the component to be change detected.
}

这是一个非常糟糕的私人方法,所以如果你有更好/更正确的解决方案,请告诉我,我会改变答案

答案 1 :(得分:1)

稍微更有棱角的方式,避免使用私有方法是在步骤使用的表单控件上记录您需要执行的操作。例如,假设我们迈出了一步:

  <mat-step [stepControl]="secondFormGroup">
    <form [formGroup]="secondFormGroup">
       <!-- your controls here -->
    </form>
  </mat-step>

然后定义表单组:

this.secondFormGroup = this._formBuilder.group({
  check: [false, Validators.requiredTrue]
});

我们现在已经定义了一个伪元素“check”,它将由该步骤验证。 假设我们使用点击功能设置了一些内容:

  doClick(item) {
     this.secondFormGroup.controls.check.setValue(item === 'thevalue');     
  }

Angular材料现在将完成其余的工作,在项目=== thevalue之前,您将无法移动到该步骤。

答案 2 :(得分:0)

在每一步中添加* ngIf

<mat-step *ngIf="*expression*"></mat-step>

答案 3 :(得分:0)

此外,如果您不想私下返回,可以使用stepper's editable属性,如下所示

<mat-vertical-stepper linear>
  <mat-step [stepControl]="firstForm" label="First" [editable]="false">
    <!-- Some form controls -->
  </mat-step>
  <mat-step *ngFor="let f of additionalForms" [stepControl]="f.form"
      [label]="f.label">
    <!-- Additional Steps -->
  </mat-step>
</mat-vertical-stepper>

基于https://material.angular.io/components/stepper/overview#editable-step

答案 4 :(得分:0)

角材料8.2.3

最好是[禁用]选项,但令人难以置信的是,它们没有添加!因此,我尝试了所有方法,最终以一种干净的方式自定义步骤标题:

显示/隐藏,当然只需使用* ngIf(还有什么?)。

禁用,请根据用户的点击次数/商店状态动态地进行以下操作:

具有出色的效果:没有悬停背景效果,光标正常,单个步骤标头不可点击,仍然呈现全彩:不透明。

steps: Array<HTMLElement> = [];
subscriptions: Array<Subscription> = [];

ngAfterViewInit() {
    // Needs continuous monitoring
    this.subscriptions.push(
        this.<observable>.pipe(
            tap((data: Data) => {
                // IMPORTANT: If you have an *ngIf on the steps,
                // you have to sync the references of the HTML elements
                this.syncHTMLSteps();
                this.updateStepState(1, false); // Always disabled
                if (data.isXXX) {
                    this.updateStepState(5, false);
                } else if (data.isYYY) {
                    this.updateStepState(2, false);
                    this.updateStepState(5, true);
                }
            })
        ).subscribe());
}

ngOnDestroy() {
    this.subscriptions.forEach((subscription) => {
        if (subscription) {
            subscription.unsubscribe();
        }
    });
}

/**
 * Reads from the Dom the list of HTML elements for the steps.
 */
private syncHTMLSteps() {
    this.steps = [];
    let increment = 1;
    let stepper: HTMLElement = document.querySelector('.mat-stepper-vertical');
    if (!stepper) {
        increment = 2; // 2, because Angular adds 2 elements for each horizontal step
        stepper = document.querySelector('.mat-horizontal-stepper-header-container');
    }
    for (let i = 0; i < stepper.children.length; i += increment) {
        this.steps.push(stepper.children[i] as HTMLElement);
    }

}

/**
 * Enable/Disable the click on the step header.
 *
 * @param step The step number (starts from 1)
 * @param enabled The new state
 */
private updateStepState(step: number, enabled: boolean) {
    // If you prefer to start using step 0, remove -1 here
    this.steps[step - 1].style.pointerEvents = enabled ? '' : 'none';
}