0
votes

Within the Angular 8 Material Stepper I'm checking some form state and if it passes, then I set stepCompleted to true.

Here's a Stackblitz that demos this: https://stackblitz.com/edit/angular-mat-stepper-demo-with-fields?file=src%2Fapp%2Fapp.component.html

The problem is that Angular does not pick up on the change right away, therefore we have to click next twice. On the second click it will see the state change.

Also if we navigate back to the step and change the parameters such that the step should not proceed, Angular will still allow the step to proceed on first click, because it still sees stepCompleted as being true. It's not false until we navigate back again.

I think the right way to fix this is to inject ChangeDetectorRef and call it like this:

stepComplete() {
   //See whether the step is complete
   //if so
   this.stepCompleted = true;
   this.cd.detectChanges();
}

Thoughts?

1
probably a better way to do it. Using change detector is usually hacky, on par with setting a timeout or resolving a promise to force change detection. Can't say what the real issue is without seeing more of the set up - bryan60
Got the ChangeDetectorRef idea from this article: alligator.io/angular/stripe-elements - Ole
It's a similar concept. In this case if there is an error, then change detection needs to be triggered manually so that the form displays the error. - Ole
I mean that’s a weird case because they’re using a 3rd party library that isn’t really integrated into angular. So those functions are being called outside of ngZone so change detection isn’t triggering as it should. They could’ve actually implemented this way better using ngZone or with renderer2. Are you integrating a 3rd parry lib or something? - bryan60
No just using the angular material stepper. When next is clicked it triggers a function that sets stepComplete to true, but only if a certain condition is met. However Angular does realize that stepComplete has been set to true on the first click. It realizes it on the second click. - Ole

1 Answers

2
votes

The issue here is that button[matStepperNext] triggers navigation before you set completed property.

The solution could be using mousedown|touchstart event instead of click:

<button mat-button matStepperNext (mousedown)="toggleStep1Complete()">

Forked Stackblitz

Another thoughts is not to use button[matStepperNext] directive and trigger navigation manually:

<mat-horizontal-stepper linear #stepper>
  <mat-step label="Step 1">
    ...
    <button mat-button (click)="stepper.selected.completed = true; stepper.next()">Next</button>

Stackblitz Example

See also: