Angular Material Stepper

Angular content stepper provides a wizard-like workflow by dividing the content into logical steps.

The material stepper is responsible for logic on the CDK stepper’s foundation that drives the stepped workflow. The material stepper extends the CDK stepper and a material design style.

Stepper Variants

There are two stepper components: mat-horizontal-stepper and mat-vertical-stepper. They both are used as same way. The only difference is the orientation of the stepper.

app.component.html

 <button mat-raised-button (click)="isLinear = !isLinear" id="toggle-linear">  

  {{!isLinear ? 'Enable linear mode' : 'Disable linear mode'}}  

</button>  

<mat-horizontal-stepper [linear]="isLinear" #stepper>  

  <mat-step [stepControl]="firstFormGroup">  

    <form [formGroup]="firstFormGroup">  

      <ng-template matStepLabel>Fill out your name</ng-template>  

      <mat-form-field>  

        <mat-label>Name</mat-label>  

        <input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>  

      </mat-form-field>  

      <div>  

        <button mat-button matStepperNext>Next</button>  

      </div>  

    </form>  

  </mat-step>  

  <mat-step [stepControl]="secondFormGroup" label="Fill out your address">  

    <form [formGroup]="secondFormGroup">  

      <mat-form-field>  

        <mat-label>Address</mat-label>  

        <input matInput formControlName="secondCtrl" placeholder="Ex. 1 Main St, New York, NY"  

               required>  

      </mat-form-field>  

      <div>  

        <button mat-button matStepperPrevious>Back</button>  

        <button mat-button matStepperNext>Next</button>  

      </div>  

    </form>  

  </mat-step>  

  <mat-step>  

    <ng-template matStepLabel>Done</ng-template>  

    <p>You are now done.</p>  

    <div>  

      <button mat-button matStepperPrevious>Back</button>  

      <button mat-button (click)="stepper.reset()">Reset</button>  

    </div>  

  </mat-step>  

</mat-horizontal-stepper> 

    app.component.ts

    import {Component, OnInit} from '@angular/core';  
    
    import {FormBuilder, FormGroup, Validators} from '@angular/forms';  
    
      
    
    /** 
    
     * @title Stepper overview 
    
     */  
    
    @Component({  
    
      selector: 'stepper-overview-example',  
    
      templateUrl: 'stepper-overview-example.html',  
    
      styleUrls: ['stepper-overview-example.css'],  
    
    })  
    
    export class StepperOverviewExample implements OnInit {  
    
      isLinear = false;  
    
      firstFormGroup: FormGroup;  
    
      secondFormGroup: FormGroup;  
    
      
    
      constructor(private _formBuilder: FormBuilder) {}  
    
      
    
      ngOnInit() {  
    
        this.firstFormGroup = this._formBuilder.group({  
    
          firstCtrl: ['', Validators.required]  
    
        });  
    
        this.secondFormGroup = this._formBuilder.group({  
    
          secondCtrl: ['', Validators.required]  
    
        });  
    
      }  
    
    }

    app.component.css

    .mat-stepper-horizontal {  
    
      margin-top: 8px;  
    
    }  
    
      
    
    .mat-form-field {  
    
      margin-top: 16px;  
    
    }

    Output:

    Angular Material Stepper

    app.component.html

     <button mat-raised-button (click)="isLinear = !isLinear" id="toggle-linear">  
    
      {{!isLinear ? 'Enable linear mode' : 'Disable linear mode'}}  
    
    </button>  
    
    <mat-vertical-stepper [linear]="isLinear" #stepper>  
    
      <mat-step [stepControl]="firstFormGroup">  
    
        <form [formGroup]="firstFormGroup">  
    
          <ng-template matStepLabel>Fill out your name</ng-template>  
    
          <mat-form-field>  
    
            <mat-label>Name</mat-label>  
    
            <input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>  
    
          </mat-form-field>  
    
          <div>  
    
            <button mat-button matStepperNext>Next</button>  
    
          </div>  
    
        </form>  
    
      </mat-step>  
    
      <mat-step [stepControl]="secondFormGroup">  
    
        <form [formGroup]="secondFormGroup">  
    
          <ng-template matStepLabel>Fill out your address</ng-template>  
    
          <mat-form-field>  
    
            <mat-label>Address</mat-label>  
    
            <input matInput formControlName="secondCtrl" placeholder="Ex. 1 Main St, New York, NY"  
    
                   required>  
    
          </mat-form-field>  
    
          <div>  
    
            <button mat-button matStepperPrevious>Back</button>  
    
            <button mat-button matStepperNext>Next</button>  
    
          </div>  
    
        </form>  
    
      </mat-step>  
    
      <mat-step>  
    
        <ng-template matStepLabel>Done</ng-template>  
    
        <p>You are now done.</p>  
    
        <div>  
    
          <button mat-button matStepperPrevious>Back</button>  
    
          <button mat-button (click)="stepper.reset()">Reset</button>  
    
        </div>  
    
      </mat-step>  
    
    </mat-vertical-stepper> 

      app.component.ts

      import {Component, OnInit} from '@angular/core';  
      
      import {FormBuilder, FormGroup, Validators} from '@angular/forms';  
      
        
      
      /** 
      
       * @title Stepper vertical 
      
       */  
      
      @Component({  
      
        selector: 'stepper-vertical-example',  
      
        templateUrl: 'stepper-vertical-example.html',  
      
        styleUrls: ['stepper-vertical-example.css']  
      
      })  
      
      export class StepperVerticalExample implements OnInit {  
      
        isLinear = false;  
      
        firstFormGroup: FormGroup;  
      
        secondFormGroup: FormGroup;  
      
        
      
        constructor(private _formBuilder: FormBuilder) {}  
      
        
      
        ngOnInit() {  
      
          this.firstFormGroup = this._formBuilder.group({  
      
            firstCtrl: ['', Validators.required]  
      
          });  
      
          this.secondFormGroup = this._formBuilder.group({  
      
            secondCtrl: ['', Validators.required]  
      
          });  
      
        }  
      
      }  

        app.component.css

        .mat-stepper-vertical {  
        
          margin-top: 8px;  
        
        }  
        
          
        
        .mat-form-field {  
        
          margin-top: 16px;  
        
        }

        Output:

        Angular Material Stepper

        The Mat-horizontal-stepper selector can create a horizontal stepper, and the Mat-vertical-stepper used to make a vertical stepper. Mat-step components are placed inside either of the two stepper components.

        Labels

        The label attribute is used If a step’s label is text.

        <mat-step [stepControl]="secondFormGroup" label="Fill out the address">  

        For more complex labels, add a template with matStepLabel directive.

        <ng-template matStepLabel>Fill out your name</ng-template>  

        Label position

        For mat-horizontal-stepper, we define the position of the label. The end is the default value, while below, it will be placed under the step icon instead of on its side. The label property controls this behavior.

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

        Stepper buttons

        There are two button instructions to support navigation between many stages: matStepperPrepret and matStepperNext.

        <button mat-button matStepperPrevious>Back</button>  
        
        <button mat-button matStepperNext>Next</button> 

          Linear stepper

          The linear attribute set to mat-horizontal-stepper and mat-vertical-stepper to create a linear stepper that requires the user to complete the previous steps before proceeding to the below steps. For each mat-step, the step control feature will be set to the top-level abscontrol used to check the action’s validity.

          Below are two approaches. One uses a form for the stepper, but another uses the different form for each step.

          Alternatively, if you do not want to use angular forms, you pass in the complete property at each step, which will not allow the user to continue until it becomes true. Note that if both absolute and phase control are set, phase control will take precedence.

          <form [formGroup]="formGroup">  
          
            <mat-horizontal-stepper formArrayName="formArray" linear>  
          
              <mat-step formGroupName="0" [stepControl]="formArray.get([0])">  
          
                ...  
          
                <div>  
          
                  <button mat-button matStepperNext type="button">Next</button>  
          
                </div>  
          
              </mat-step>  
          
              <mat-step formGroupName="1" [stepControl]="formArray.get([1])">  
          
                ...  
          
                <div>  
          
                  <button mat-button matStepperPrevious type="button">Back</button>  
          
                  <button mat-button matStepperNext type="button">Next</button>  
          
                </div>  
          
              </mat-step>  
          
              ...  
          
            </mat-horizontal-stepper>  
          
          </form>  

            Using a different form for each step

            <mat-vertical-stepper linear>  
            
              <mat-step [stepControl]="formGroup1">  
            
                <form [formGroup]="formGroup1">  
            
                  ...  
            
                </form>  
            
              </mat-step>  
            
              <mat-step [stepControl]="formGroup2">  
            
                <form [formGroup]="formGroup2">  
            
                  ...  
            
                </form>  
            
              </mat-step>  
            
            </mat-vertical-stepper> 

              Types of steps

              Optional step

              If completing a linear stepper step is not required, then the optional attribute is set on the mat-step.

              <mat-step [stepControl]="secondFormGroup" [optional]="isOptional">  

              Editable step

              By default, the steps are editable, which means that users can return to previously completed actions and edit their responses.

              <mat-step [stepControl]="firstFormGroup" [editable]="isEditable">  

              Completed step

              By default, the phase’s absolute attribute is corrected if the stage is valid (in the case of linear stepper) and the user has interacted with the phase. However, the user can also override the built-in attribute as required by this default complete behavior.

              Overriding icons

              By default, step headers use icons created and made from the Material Design icon set via the <mat-icon> elements. If you want to provide many sets of icons, you can do this by placing a MatsapperIcon for each icon that you want to override. Indicative, active, and alternative values of individual phases are available by the template variable:

                <ng-template matStepperIcon="phone">  
              
                  <mat-icon>call_end</mat-icon>  
              
                </ng-template>  
              
                <ng-template matStepperIcon="chat">  
              
                  <mat-icon>forum</mat-icon>  
              
                </ng-template>  
              
              </mat-horizontal-stepper>  

                Note that you aren’t limited to using the mat-icon component when providing custom icons.

                Step States

                You can set a step position when you want. The position given to an icon by the default map. However, it can be overridden in the same way as above.

                 <mat-horizontal-stepper>  
                
                  <mat-step label="Step 1" state="phone">  
                
                    <p>Put down your phones.</p>  
                
                    <div>  
                
                      <button mat-button matStepperNext>Next</button>  
                
                    </div>  
                
                  </mat-step>  
                
                  <mat-step label="Step 2" state="chat">  
                
                    <p>Socialize with each other.</p>  
                
                    <div>  
                
                      <button mat-button matStepperPrevious>Back</button>  
                
                      <button mat-button matStepperNext>Next</button>  
                
                    </div>  
                
                  </mat-step>  
                
                  <mat-step label="Step 3">  
                
                    <p>You're welcome.</p>  
                
                  </mat-step>  
                
                  
                
                  <!-- Icon overrides. -->  
                
                  <ng-template matStepperIcon="phone">  
                
                    <mat-icon>call_end</mat-icon>  
                
                  </ng-template>  
                
                  <ng-template matStepperIcon="chat">  
                
                    <mat-icon>forum</mat-icon>  
                
                  </ng-template>  
                
                </mat-horizontal-stepper> 

                  In order to use the custom step states, you should add the displayDefaultIndicatorType option to the global default stepper which can be specified by providing a value for STEPPER_GLOBAL_OPTIONS in the application’s root module.

                   @NgModule({  
                  
                    providers: [  
                  
                      {  
                  
                        provide: STEPPER_GLOBAL_OPTIONS,  
                  
                        useValue: { displayDefaultIndicatorType: false }  
                  
                      }  
                  
                    ]  
                  
                  }) 

                    app.component.html

                     <mat-horizontal-stepper #stepper>  
                    
                      <mat-step [stepControl]="firstFormGroup">  
                    
                        <form [formGroup]="firstFormGroup">  
                    
                          <ng-template matStepLabel>Fill out your name</ng-template>  
                    
                          <mat-form-field>  
                    
                            <mat-label>Name</mat-label>  
                    
                            <input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>  
                    
                          </mat-form-field>  
                    
                          <div>  
                    
                            <button mat-button matStepperNext>Next</button>  
                    
                          </div>  
                    
                        </form>  
                    
                      </mat-step>  
                    
                      <mat-step [stepControl]="secondFormGroup">  
                    
                        <form [formGroup]="secondFormGroup">  
                    
                          <ng-template matStepLabel>Fill out your address</ng-template>  
                    
                          <mat-form-field>  
                    
                            <mat-label>Address</mat-label>  
                    
                            <input matInput formControlName="secondCtrl" placeholder="Ex. 1 Main St, New York, NY"  
                    
                                   required>  
                    
                          </mat-form-field>  
                    
                          <div>  
                    
                            <button mat-button matStepperPrevious>Back</button>  
                    
                            <button mat-button matStepperNext>Next</button>  
                    
                          </div>  
                    
                        </form>  
                    
                      </mat-step>  
                    
                      <mat-step>  
                    
                        <ng-template matStepLabel>Done</ng-template>  
                    
                        <p>You are now done.</p>  
                    
                        <div>  
                    
                          <button mat-button matStepperPrevious>Back</button>  
                    
                          <button mat-button (click)="stepper.reset()">Reset</button>  
                    
                        </div>  
                    
                      </mat-step>  
                    
                    </mat-horizontal-stepper>  
                    
                      
                    
                    <mat-horizontal-stepper>  
                    
                      <mat-step label="Step 1" state="phone">  
                    
                        <p>Put down your phones.</p>  
                    
                        <div>  
                    
                          <button mat-button matStepperNext>Next</button>  
                    
                        </div>  
                    
                      </mat-step>  
                    
                      <mat-step label="Step 2" state="chat">  
                    
                        <p>Socialize with each other.</p>  
                    
                        <div>  
                    
                          <button mat-button matStepperPrevious>Back</button>  
                    
                          <button mat-button matStepperNext>Next</button>  
                    
                        </div>  
                    
                      </mat-step>  
                    
                      <mat-step label="Step 3">  
                    
                        <p>You're welcome.</p>  
                    
                      </mat-step>  
                    
                      
                    
                      <!-- Icon overrides. -->  
                    
                      <ng-template matStepperIcon="phone">  
                    
                        <mat-icon>call_end</mat-icon>  
                    
                      </ng-template>  
                    
                      <ng-template matStepperIcon="chat">  
                    
                        <mat-icon>forum</mat-icon>  
                    
                      </ng-template>  
                    
                    </mat-horizontal-stepper> 

                      app.component.ts

                      import {Component, OnInit} from '@angular/core';  
                      
                      import {FormBuilder, FormGroup, Validators} from '@angular/forms';  
                      
                      import {STEPPER_GLOBAL_OPTIONS} from '@angular/cdk/stepper';  
                      
                        
                      
                      /** 
                      
                       * @title Stepper with customized states 
                      
                       */  
                      
                      @Component({  
                      
                        selector: 'stepper-states-example',  
                      
                        templateUrl: 'stepper-states-example.html',  
                      
                        styleUrls: ['stepper-states-example.css'],  
                      
                        providers: [{  
                      
                          provide: STEPPER_GLOBAL_OPTIONS, useValue: {displayDefaultIndicatorType: false}  
                      
                        }]  
                      
                      })  
                      
                      export class StepperStatesExample implements OnInit {  
                      
                        firstFormGroup: FormGroup;  
                      
                        secondFormGroup: FormGroup;  
                      
                        
                      
                        constructor(private _formBuilder: FormBuilder) {}  
                      
                        
                      
                        ngOnInit() {  
                      
                          this.firstFormGroup = this._formBuilder.group({  
                      
                            firstCtrl: ['', Validators.required]  
                      
                          });  
                      
                          this.secondFormGroup = this._formBuilder.group({  
                      
                            secondCtrl: ['', Validators.required]  
                      
                          });  
                      
                        }  
                      
                      } 

                        app.component.css

                        .mat-stepper-horizontal {  
                        
                          margin-top: 8px;  
                        
                        }  
                        
                          
                        
                        .mat-form-field {  
                        
                          margin-top: 16px;  
                        
                        }

                        Output:

                        Angular Material Stepper

                        Error State

                        If you want to show an error when the user moved past a step that hasn’t been filled correctly. Then, you can set the error message by the errorMessage input and configure the stepper to show errors by the showError option in the STEPPER_GLOBAL_OPTIONS injection token.

                        @NgModule({  
                        
                          providers: [  
                        
                            {  
                        
                              provide: STEPPER_GLOBAL_OPTIONS,  
                        
                              useValue: { showError: true }  
                        
                            }  
                        
                          ]  
                        
                        }) 

                          app.component.html

                          <mat-horizontal-stepper #stepper>  
                          
                            <mat-step [stepControl]="firstFormGroup" errorMessage="Name is required.">  
                          
                              <form [formGroup]="firstFormGroup">  
                          
                                <ng-template matStepLabel>Fill out your name</ng-template>  
                          
                                <mat-form-field>  
                          
                                  <mat-label>Name</mat-label>  
                          
                                  <input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>  
                          
                                </mat-form-field>  
                          
                                <div>  
                          
                                  <p>Go to a different step to see the error state</p>  
                          
                                  <button mat-button matStepperNext>Next</button>  
                          
                                </div>  
                          
                              </form>  
                          
                            </mat-step>  
                          
                            <mat-step [stepControl]="secondFormGroup" errorMessage="Address is required.">  
                          
                              <form [formGroup]="secondFormGroup">  
                          
                                <ng-template matStepLabel>Fill out your address</ng-template>  
                          
                                <mat-form-field>  
                          
                                  <mat-label>Address</mat-label>  
                          
                                  <input matInput placeholder="Ex. 1 Main St, New York, NY" formControlName="secondCtrl"  
                          
                                         required>  
                          
                                </mat-form-field>  
                          
                                <div>  
                          
                                  <p>Go to a different step to see the error state</p>  
                          
                                  <button mat-button matStepperPrevious>Back</button>  
                          
                                  <button mat-button matStepperNext>Next</button>  
                          
                                </div>  
                          
                              </form>  
                          
                            </mat-step>  
                          
                            <mat-step>  
                          
                              <ng-template matStepLabel>Done</ng-template>  
                          
                              <p>You are now done.</p>  
                          
                              <div>  
                          
                                <button mat-button matStepperPrevious>Back</button>  
                          
                                <button mat-button (click)="stepper.reset()">Reset</button>  
                          
                              </div>  
                          
                            </mat-step>  
                          
                          </mat-horizontal-stepper> 

                            app.component.ts

                             import {Component, OnInit} from '@angular/core';  
                            
                            import {FormBuilder, FormGroup, Validators} from '@angular/forms';  
                            
                            import {STEPPER_GLOBAL_OPTIONS} from '@angular/cdk/stepper';  
                            
                              
                            
                            /** 
                            
                             * @title Stepper that displays errors in the steps 
                            
                             */  
                            
                            @Component({  
                            
                              selector: 'stepper-errors-example',  
                            
                              templateUrl: 'stepper-errors-example.html',  
                            
                              styleUrls: ['stepper-errors-example.css'],  
                            
                              providers: [{  
                            
                                provide: STEPPER_GLOBAL_OPTIONS, useValue: {showError: true}  
                            
                              }]  
                            
                            })  
                            
                            export class StepperErrorsExample implements OnInit {  
                            
                              firstFormGroup: FormGroup;  
                            
                              secondFormGroup: FormGroup;  
                            
                              
                            
                              constructor(private _formBuilder: FormBuilder) {}  
                            
                              
                            
                              ngOnInit() {  
                            
                                this.firstFormGroup = this._formBuilder.group({  
                            
                                  firstCtrl: ['', Validators.required]  
                            
                                });  
                            
                                this.secondFormGroup = this._formBuilder.group({  
                            
                                  secondCtrl: ['', Validators.required]  
                            
                                });  
                            
                              }  
                            
                            } 

                              app.component.css

                              .mat-form-field {  
                              
                                margin-top: 16px;  
                              
                              }

                              Output:

                              Angular Material Stepper
                              Angular Material Stepper

                              Keyboard interaction

                              • LEFT_ARROW: It focuses on the previous step header
                              • RIGHT_ARROW: It focuses on the following step header
                              • HOME: It focuses on the first step header
                              • END: It focuses on the last step header
                              • ENTER, SPACE: It selects the step where the focus is currently on
                              • TAB: Focuses It is the next tabbable element
                              • SHIFT+TAB: It focuses on the previous tabbable element

                              Localizing labels

                              Localization of messages is done by providing a subclass with translated values in the root module.

                              @NgModule({  
                              
                                imports: [MatStepperModule],  
                              
                                providers: [  
                              
                                  {provide: MatStepperIntl, useClass: MyIntl},  
                              
                                ],  
                              
                              })  
                              
                              export class MyApp {}

                              Accessibility

                              The stepper is treated as a tabbed view for accessibility purposes, so it is given role = “tablist” by default. The step header’s aria-selected feature and the aria-extended quality of the step content are set based on the phase selection change.

                              The area label or the area-labeledby gives the stepper and each step a meaningful label.


                              Comments

                              Leave a Reply

                              Your email address will not be published. Required fields are marked *