Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Material Design - stepper how to remove/disable steps?

I'm using Material - Angular2 Stepper, and I have additional steps that I want to add/enable depending on what the user selects in the first step.

I tried the following:
- Load the additional forms into an array,
- then loop through it in the template with *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 works well for adding new steps, the problem is I can't remove them. If the user happened to come back to first form, and uncheck something, these additional steps wouldn't be required.

So trying something like: this.additionalForms = [] doesn't remove the steps. (until you click on one of the "removed" steps, then it throws an error: Cannot read property 'editable' of undefined, and only then, they're removed visually)

I also tried doing ChangeDetectorRef.detectChanges()
and tried wrapping into the NgZone.run()

but made no difference

Any solutions for this?

like image 959
user7552 Avatar asked Oct 12 '17 12:10

user7552


3 Answers

So I managed with this work-around:
https://github.com/angular/material2/issues/7700#issuecomment-336138411

1) Make a reference to the stepper:

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

2) Then, on the .ts side:

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

This is calling a private method which is probably a really bad idea, so if you have a better/correct solution, let me know, and I'll change the answer

like image 109
user7552 Avatar answered Nov 08 '22 12:11

user7552


Add *ngIf in each step

<mat-step *ngIf="*expression*"></mat-step>
like image 2
Nikita Tsygankov Avatar answered Nov 08 '22 11:11

Nikita Tsygankov


A slightly more angular way, avoiding the private method way is to record what you need to do on the form control used by the step. So for instance let's say we have a step:

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

Then define your form group:

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

We have now defined a pseudo element "check", that will be validated by the step. Let's say we set something with a click function:

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

Angular material will now do the rest, you will not be able to move past the step until item === thevalue.

like image 4
PeterS Avatar answered Nov 08 '22 13:11

PeterS