Search code examples
angularangular-materialangular-material2

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


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>

Solution

  • 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>