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?
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
Add *ngIf in each step
<mat-step *ngIf="*expression*"></mat-step>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With