Twitter LogoFacebook Logo
Angular Material UI: Stepper
The Stepper component allows us to traverse through content 1 step at a time.
By: King

The Stepper component allows us to traverse through content 1 step at a time.


There are 2 variants to the Stepper component. The Horizontal Stepper and the Vertical Stepper.

Image from Codeible.com
Image from Codeible.com

Implementation

To begin, add the MatStepperModule to the project. Go into the app module file and add the import statement. Then add it to the app.

...
import { MatStepperModule } from '@angular/material/stepper';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    ...
    MatStepperModule,

  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Using the Stepper

To add the stepper, use the mat-horizontal-stepper or the mat-vertical-stepper element.

<mat-horizontal-stepper></mat-horizontal-stepper >

<mat-vertical-stepper></mat-vertical-stepper>

To add the steps, place the mat-step element inside the stepper. Use 1 for each step.

<mat-horizontal-stepper>

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
</mat-horizontal-stepper>

To label the steps, set the label attribute with some text.

 <mat-step label="Step 1">...</mat-step>

Image from Codeible.com

Instead of displaying the labels next to the steps icon, we can place them underneath. Apply the labelPosition attribute to the stepper and set it to bottom.

<mat-horizontal-stepper labelPosition="bottom">

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
</mat-horizontal-stepper>

Image from Codeible.com

Custom Labels

For more complex labels, remove the label attribute and add a ng-template element inside the step. Then apply the matStepLabel property.

<mat-horizontal-stepper labelPosition="bottom">

     <mat-step>
         <ng-template matStepLabel>

          </ng-template>
     </mat-step>
     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
</mat-horizontal-stepper>

Inside the template, we can place the contents for our label.

<mat-step>
     <ng-template matStepLabel>
         Register For
         <img
           src="https://codeible.com/assets/images/icons/codible_256.png" width="32px">
     </ng-template>
</mat-step>

Image from Codeible.com

Adding Content

To add the content for each step, place your code inside the step element as you would do for a div element.

<mat-step>
     <ng-template matStepLabel>
         Register For
         <img
           src="https://codeible.com/assets/images/icons/codible_256.png" width="32px">
     </ng-template>

      <div>
           <input placeholder="Email"/>
      </div>
</mat-step>

Image from Codeible.com

Next and Back Buttons

The stepper module also comes with 2 button directives that we can add to the buttons inside the step so we can traverse back and forth between them.

Use the matStepperNext directive for the next button and the matStepperPrevious directive for the back button.

<mat-step>
      ...
      <div>
           <button matStepperNext>Next</button>
           <button matStepperPrevious >Back</button>
      </div>
</mat-step>

To stop the user from going back, apply the linear attribute to the stepper. Then apply the editable property to the step and set it to false. 

<mat-horizontal-stepper linear>


     <mat-step [editable]="false">
         ...
     </mat-step>

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
</mat-horizontal-stepper>

This will stop the user from going back to the step once they move on from it.

To stop the user from going forward until the step is completed, apply the completed property to the step and set it to false

The user will not be able to go forward unless the completed property is set to true.

You can set some condition inside the step for the user to complete in order for  them to move forward.

<mat-step [completed]="false">
         ...
</mat-step>

Using FormGroup Validation

Alternatively, if you are familiar with FormGroup validation, you can use it as well. Define the FormGroup in the TypeScript file.

Import AbstractControl, FormBuilder, FormGroup, ValidatorFn, and Validators from @angular forms and then declare a FormGroup.

TypeScript

...
import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';

@Component({
  ...
})
export class AppComponent {

  registrationGroup: FormGroup;

  constructor(){
 
  }

}

Inject FormBuilder in the constructor and create the group. 

registrationGroup: FormGroup;

constructor(private _formBuilder: FormBuilder){
    this.registrationGroup = this._formBuilder.group({
        emailValidator: ['', Validators.compose([Validators.required])]
    });
}

Then attach the group to the step. In the HTML page, apply the stepControl attribute to the step and pass in the group object.


Wrap all the elements in the step with a form element and set the formGroup attribute to the formGroup as well.

Lastly, add an input element and pass in the validator name using the formControlName property. This will stop the user from moving to the next step unless they met the requirements based on the FormGroup.

HTML

<mat-horizontal-stepper linear>


     <mat-step [stepControl]="registrationGroup">
         <form [formGroup]="registrationGroup">
              ...
              <div>
                   <input formControlName="emailValidator" />
              </div>
        </form>
     </mat-step>

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
</mat-horizontal-stepper>

Do not forget to add the Forms and ReactiveForms modules to your project.


import { FormsModule, ReactiveFormsModule } from '@angular/forms';

Optional Steps

We can also use the optional attribute to enable the user to skip the step even though there is a FormGroup or the completed attribute attached to it.

Image from Codeible.com

<mat-horizontal-stepper linear>


     <mat-step [stepControl]="registrationGroup" [optional]="true">
         <form [formGroup]="registrationGroup">
              ...
              <div>
                   <input formControlName="emailValidator" />
              </div>
        </form>
     </mat-step>

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
</mat-horizontal-stepper>

Displaying Error Messages

Instead of locking the user from going to the next step, we can display an error message instead.

Remove the linear attribute from the stepper. Then apply the errorMessage attribute to the step and give it an error message that you want to show.

<mat-horizontal-stepper>


     <mat-step errorMessage="Email is Incorrect" [stepControl]="registrationGroup">
         <form [formGroup]="registrationGroup">
              ...
              <div>
                   <input formControlName="emailValidator" />
              </div>
        </form>
     </mat-step>

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
</mat-horizontal-stepper>

Then go into the TypeScript file and configure the stepper to show errors.

Import STEPPER_GLOBAL_OPTIONS and then add the provider to the component. This will enable us to show errors if the user fails met the requirements.

...
import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';


@Component({
  selector: '...',
  templateUrl: '...',
  styleUrls: ['...'],
  providers: [{
    provide: STEPPER_GLOBAL_OPTIONS
    useValue: { showError: true }
  }]
})
export class AppComponent {
  ...
}

Custom Stepper Icons

Image from Codeible.com

We can also change the icon of the steps. Set the displayDefaultIndicatorType of the stepper to false in the stepper configuration.

  providers: [{
    provideSTEPPER_GLOBAL_OPTIONS
    useValue: { 
        showError: true,
        displayDefaultIndicatorType: false 
    }
  }]

Then create a template to replace the icon using the ng-template element in the stepper element. You can put whatever you want inside the template. For example, we can use an image

HTML

<mat-horizontal-stepper>

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>
     <mat-step>...</mat-step>

     <ng-template>
          <img src="https://codeible.com/assets/images/icons/codible_256.png" width="32px">
     </ng-template>
</mat-horizontal-stepper>

Then apply the matStepperIcon attribute to the template and give it a name.

<ng-template matStepperIcon="registerIcon">
          <img src="..." width="32px">
</ng-template>

Lastly, add apply the state attribute to the step you want to replace the icon with and set it to the name of the template that you want to use as the icon.

<mat-horizontal-stepper>


     <mat-step state="registerIcon">...</mat-step>

     <mat-step>...</mat-step>
     <mat-step>...</mat-step>

     <ng-template matStepperIcon="registerIcon">
          <img src="https://codeible.com/assets/images/icons/codible_256.png" width="32px">
     </ng-template>

</mat-horizontal-stepper>


Sign In