angularangular7angular-routinguistepper

Angular 7 - Stepper component working with routing


I need an checked solution of Stepper component for Angular 7, that works with Angular routing.

Not a Material Design Stepper - it does work well for simple forms, but not routing.

What I tried to do, with <mat-horizontal-stepper>, was something like this:

component.html:

<mat-horizontal-stepper (selectionChange)="selectionChanged($event)" [linear]="true">
    <mat-step *ngFor="let step of steps; let i = index" [label]="step.title">
        <router-outlet *ngIf="i === selectedStepIndex"></router-outlet>
    </mat-step>
</mat-horizontal-stepper>

component.ts:

public selectedStepIndex: number = 0;

selectionChanged(event: any) {
    this.selectedStepIndex= event.selectedIndex;
    const url = '/some-path/' + this.links[this.selectedStepIndex].path;
    this.router.navigate([url]);//using -> private router: Router
}

However, I can not navigate back for some reason. Stepper tries to navigate back, but it shows the same page, unless it is the first page of stepper (i = 0).

I would be greatful for any recommendation (and maybe working example), or a detailed information about how to achive this with <mat-horizontal-stepper>.


Solution

  • Alright! I have figured it out :)

    It looks like <mat-horizontal-stepper> needs some time to reaload showed step, when it comes to <router-outlet> - so I had to manually force him to wait. Do something like this, and it will work good enough:

    component.html:

    <mat-horizontal-stepper (selectionChange)="selectionChanged($event)" [linear]="true">
        <mat-step *ngFor="let step of steps; let i = index" [label]="step.title">
            <div *ngIf="loadingStep">
                <mat-spinner></mat-spinner>
            </div>
            <div *ngIf="!loadingStep">
                <router-outlet *ngIf="i === selectedStepIndex"></router-outlet>
            </div>
        </mat-step>
    </mat-horizontal-stepper>
    

    component.ts:

    public selectedStepIndex: number = 0;
    public loadingStep: boolean = false;
    
    selectionChanged(event: any) {
        this.selectedStepIndex = event.selectedIndex;
        if (event.previouslySelectedIndex > event.selectedIndex) {
            this.loadingStep = true;
            //Wait 1 sec. before showing the step
            setTimeout(() => {
                this.navigate();
                this.loadingStep = false;
            }, 1000);
        } else {
            this.navigate();
        }
    }
    
    private navigate(): void {
        const url = '/some-path/' + this.links[this.selectedStepIndex].path;
        this.router.navigate([url]);//using -> private router: Router
    }
    

    It is not perfect, but it is good enough for me :))