Can I programmatically move the steps of a mat-horizontal-stepper in Angular / Angular Material

Mike Sav picture Mike Sav · Sep 28, 2017 · Viewed 81.3k times · Source

I have a question regards Angular Material (with Angular 4+). Say in my component template I add a <mat-horizontal-stepper> component, and within each step <mat-step> I have stepper buttons to navigate the component. Like so...

<mat-horizontal-stepper>
  <mat-step>
    Step 1
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
  <mat-step>
    Step 2
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
  <mat-step>
    Step 3
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
</mat-horizontal-stepper>

Now I am wondering if it is possible to remove the buttons out of each step and have them elsewhere in the <mat-horizontal-stepper> in a static position or even outside the <mat-horizontal-stepper> and I can navigate backwards and forwards using code within my component typescript file. To give an idea, I would like my HTML be something like this

<mat-horizontal-stepper>
    <mat-step>
        Step 1
    </mat-step>
    <mat-step>
        Step 2
    </mat-step>
    <mat-step>
        Step 3
    </mat-step>
    <!-- one option -->
    <div>
       <button mat-button matStepperPrevious type="button">Back</button>
       <button mat-button matStepperNext type="button">Next</button>
    </div>
</mat-horizontal-stepper>

<!-- second option -->
<div>
   <button (click)="goBack()" type="button">Back</button>
   <button (click)="goForward()" type="button">Next</button>
</div>

Answer

Faisal picture Faisal · Sep 28, 2017

Yes. It is possible to jump to a specific stepper by using selectedIndex property of the MatStepper. Also, MatStepper exposes public methods next() and previous(). You can use them to move back and forth.

In your template:

Add an id to your stepper e.g. #stepper. Then in your goBack() and goForward() methods, pass the stepper id:

<mat-horizontal-stepper #stepper>
    <!-- Steps -->
</mat-horizontal-stepper>    
<!-- second option -->
<div>
   <button (click)="goBack(stepper)" type="button">Back</button>
   <button (click)="goForward(stepper)" type="button">Next</button>
</div>

.. and in your typescript:

import { MatStepper } from '@angular/material/stepper';

goBack(stepper: MatStepper){
    stepper.previous();
}

goForward(stepper: MatStepper){
    stepper.next();
}

Link to stackblitz demo.


You can also use ViewChild to get a reference to the stepper component in your TypeScript as shown below:

@ViewChild('stepper') private myStepper: MatStepper;

goBack(){
    this.myStepper.previous();
}

goForward(){
    this.myStepper.next();
}

In this case, you don't have to pass the stepper reference in the method in your component's html. Link to Demo with ViewChild


You can enable/disable the Back and Next buttons by using the following:

<button (click)="goBack(stepper)" type="button" 
        [disabled]="stepper.selectedIndex === 0">Back</button>
<button (click)="goForward(stepper)" type="button" 
        [disabled]="stepper.selectedIndex === stepper._steps.length-1">Next</button>