Angular Bootstrap Steppers

Angular Steps (stepper) - Bootstrap 4 & Material Design

Note: This documentation is for an older version of Bootstrap (v.4). A newer version is available for Bootstrap 5. We recommend migrating to the latest version of our product - Material Design for Bootstrap 5.
Go to docs v.5

Angular Bootstrap stepper is a component that displays content as a process with defined by user milestones. Following steps are separated and connected by buttons.

This is a great solution for a variety of registration forms, where you don't want to scare the user with loads of fields and questions.

Stepper can be aligned vertically as well as horizontally.

Examples of Bootstrap steps use:

  • Registration form
  • Payment gateway
  • Tutorial with steps

See the following Bootstrap stepper examples:


Basic horizontal steppers



        <!-- Horizontal Steppers -->
        <div class="row">
          <div class="col-md-12">

            <!-- Stepers Wrapper -->
            <ul class="stepper stepper-horizontal">

              <!-- First Step -->
              <li class="completed">
                <a href="#!">
                  <span class="circle">1</span>
                  <span class="label">First step</span>
                </a>
              </li>

              <!-- Second Step -->
              <li class="active">
                <a href="#!">
                  <span class="circle">2</span>
                  <span class="label">Second step</span>
                </a>
              </li>

              <!-- Third Step -->
              <li class="warning">
                <a href="#!">
                  <span class="circle"><mdb-icon fas icon="exclamation"></mdb-icon></span>
                  <span class="label">Third step</span>
                </a>
              </li>

            </ul>
            <!-- /.Stepers Wrapper -->

          </div>
        </div>
        <!-- /.Horizontal Steppers -->
      

Basic vertical steppers

  • 1 First step
  • 2 Second step

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Esse cupiditate voluptate facere iusto quaerat vitae excepturi, accusantium ut aliquam repellat atque nesciunt nostrum similique. Inventore nostrum ut, nobis porro sapiente.

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore error excepturi veniam nemo repellendus, distinctio soluta vitae at sit saepe. Optio eaque quia excepturi adipisci pariatur totam, atque odit fugiat.

    Deserunt voluptatem illum quae nisi soluta eum perferendis nesciunt asperiores tempore saepe reiciendis, vero quod a dolor corporis natus qui magni quas fuga rem excepturi laboriosam. Quisquam expedita ab fugiat.

  • Third step
  • 4 Fourth step



        <!-- Vertical Steppers -->
        <div class="row mt-1">
          <div class="col-md-12">

            <!-- Stepers Wrapper -->
            <ul class="stepper stepper-vertical">

              <!-- First Step -->
              <li class="completed">
                <a href="#!">
                  <span class="circle">1</span>
                  <span class="label">First step</span>
                </a>
              </li>

              <!-- Second Step -->
              <li class="active">

                <!--Section Title -->
                <a href="#!">
                  <span class="circle">2</span>
                  <span class="label">Second step</span>
                </a>

                <!-- Section Description -->
                <div class="step-content grey lighten-3">
                  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Esse cupiditate voluptate facere
                    iusto
                    quaerat
                    vitae excepturi, accusantium ut aliquam repellat atque nesciunt nostrum similique. Inventore
                    nostrum
                    ut,
                    nobis porro sapiente.</p>
                  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore error excepturi veniam nemo
                    repellendus, distinctio soluta vitae at sit saepe. Optio eaque quia excepturi adipisci pariatur
                    totam,
                    atque odit fugiat.</p>
                  <p>Deserunt voluptatem illum quae nisi soluta eum perferendis nesciunt asperiores tempore saepe
                    reiciendis,
                    vero quod a dolor corporis natus qui magni quas fuga rem excepturi laboriosam. Quisquam
                    expedita ab
                    fugiat.</p>
                </div>
              </li>

              <!-- Third Step -->
              <li class="warning">
                <a href="#!">
                  <span class="circle"><mdb-icon fas icon="exclamation"></mdb-icon></span>
                  <span class="label">Third step</span>
                </a>
              </li>

              <!-- Fourth Step -->
              <li>
                <a href="#!">
                  <span class="circle">4</span>
                  <span class="label">Fourth step</span>
                </a>
              </li>

            </ul>
            <!-- /.Stepers Wrapper -->

          </div>
        </div>

        <!-- Steppers Navigation -->
        <div class="row mt-1">
          <div class="col-md-12 text-right">
            <button mdbBtn flat="true" size="sm">Cancel</button>
            <button mdbBtn color="primary" size="sm">Next</button>
          </div>
        </div>
        <!-- /.Vertical Steppers -->

      

Linear Stepper MDB Pro component

Linear stepper is a compontent which is the most common. If you need to activate linear mode, add [linear]="true" input to the mdb-stepper component.

When you are working with this stepper you have to put a correct values to do more steps.

  • Step 1
  • Step 2
  • Step 3
    Finish!


        <mdb-stepper #stepper [linear]="true">
          <mdb-step name="Step 1" [stepForm]="firstFormGroup">
            <form [formGroup]="firstFormGroup">
              <div class="md-form">
                <input type="text" class="form-control" mdbInput mdbValidate formControlName="email">
                <label for="">Email</label>
                <mdb-error *ngIf="email.invalid && (email.dirty || email.touched)">Input invalid</mdb-error>
                <mdb-success *ngIf="email.valid && (email.dirty || email.touched)">Input valid</mdb-success>
              </div>
            </form>
            <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
          </mdb-step>
          <mdb-step name="Step 2" [stepForm]="secondFormGroup">
            <form [formGroup]="secondFormGroup">
              <div class="md-form">
                <input type="password" class="form-control" mdbInput mdbValidate formControlName="password">
                <label for="">Password</label>
                <mdb-error *ngIf="password.invalid && (password.dirty || password.touched)">Input invalid</mdb-error>
                <mdb-success *ngIf="password.valid && (password.dirty || password.touched)">Input valid</mdb-success>
              </div>
            </form>
            <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
            <button mdbBtn size="sm" color="secondary" (click)="stepper.previous()">BACK</button>
          </mdb-step>
          <mdb-step name="Step 3" label="Step 3 label">
            <p class="pl-2">Finish!</p>
            <div class="step-actions">
              <button mdbBtn  size="sm" color="primary" (click)="onSubmit()">SUBMIT</button>
            </div>
          </mdb-step>
        </mdb-stepper>


      


        import { Component, OnInit } from '@angular/core';
        import { FormGroup, FormControl, Validators } from '@angular/forms';

        @Component({
          selector: 'linear-stepper',
          templateUrl: './linear-stepper.component.html',
        })
        export class LinearStepperComponent implements OnInit {
          firstFormGroup: FormGroup;
          secondFormGroup: FormGroup;

          ngOnInit() {
            this.firstFormGroup = new FormGroup({
              email: new FormControl('', [Validators.required, Validators.email])
            });
            this.secondFormGroup = new FormGroup({
              password: new FormControl('', Validators.required)
            });
          }

          get email() { return this.firstFormGroup.get('email'); }
          get password() { return this.secondFormGroup.get('password'); }

          onSubmit() {
            // do something here
          }

        }
      

Non-linear Stepper MDB Pro component

With non linear stepper you can navigate freely between every steps.

  • Step 1
  • Step 2
  • Step 3
    Finish!


        <mdb-stepper #stepper>
          <mdb-step name="Step 1" [stepForm]="firstFormGroup">
            <form [formGroup]="firstFormGroup">
              <div class="md-form">
                <input type="text" class="form-control" mdbInput mdbValidate formControlName="email">
                <label for="">Email</label>
                <mdb-error *ngIf="email.invalid && (email.dirty || email.touched)">Input invalid</mdb-error>
                <mdb-success *ngIf="email.valid && (email.dirty || email.touched)">Input valid</mdb-success>
              </div>
            </form>
            <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
          </mdb-step>
          <mdb-step name="Step 2" [stepForm]="secondFormGroup">
            <form [formGroup]="secondFormGroup">
              <div class="md-form">
                <input type="password" class="form-control" mdbInput mdbValidate formControlName="password">
                <label for="">Password</label>
                <mdb-error *ngIf="password.invalid && (password.dirty || password.touched)">Input invalid</mdb-error>
                <mdb-success *ngIf="password.valid && (password.dirty || password.touched)">Input valid</mdb-success>
              </div>
            </form>
            <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
            <button mdbBtn size="sm" color="secondary" (click)="stepper.previous()">BACK</button>
          </mdb-step>
          <mdb-step name="Step 3" label="Step 3 label">
            <p class="pl-2">Finish!</p>
            <div class="step-actions">
              <button mdbBtn  size="sm" color="primary" (click)="onSubmit()">SUBMIT</button>
            </div>
          </mdb-step>
        </mdb-stepper>


      

          import { Component, OnInit } from '@angular/core';
          import { FormGroup, FormControl, Validators } from '@angular/forms';

          @Component({
            selector: 'non-linear-stepper',
            templateUrl: './non-linear-stepper.component.html',
          })
          export class NonLinearStepperComponent implements OnInit {
            firstFormGroup: FormGroup;
            secondFormGroup: FormGroup;

            ngOnInit() {
              this.firstFormGroup = new FormGroup({
                email: new FormControl('', [Validators.required, Validators.email])
              });
              this.secondFormGroup = new FormGroup({
                password: new FormControl('', Validators.required)
              });
            }

            get email() { return this.firstFormGroup.get('email'); }
            get password() { return this.secondFormGroup.get('password'); }

            onSubmit() {
              // do something here
            }

          }
      

Vertical Stepper MDB Pro component

By default steppers have horizontal orientation. In order to chanage it to vertical, you need to use [vertical]="true" input.

  • Step 1
  • Step 2
  • Step 3
    Finish!

        <mdb-stepper #stepper [vertical]="true">
            <mdb-step name="Step 1" label="Type something" [stepForm]="firstFormGroup">
              <form [formGroup]="firstFormGroup">
                <div class="md-form">
                  <input type="text" class="form-control" mdbInput mdbValidate formControlName="email">
                  <label for="">Email</label>
                  <mdb-error *ngIf="email.invalid && (email.dirty || email.touched)">Input invalid</mdb-error>
                  <mdb-success *ngIf="email.valid && (email.dirty || email.touched)">Input valid</mdb-success>
                </div>
              </form>
              <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
            </mdb-step>
            <mdb-step name="Step 2" [stepForm]="secondFormGroup">
              <form [formGroup]="secondFormGroup">
                <div class="md-form">
                  <input type="password" class="form-control" mdbInput mdbValidate formControlName="password">
                  <label for="">Password</label>
                  <mdb-error *ngIf="password.invalid && (password.dirty || password.touched)">Input invalid</mdb-error>
                  <mdb-success *ngIf="password.valid && (password.dirty || password.touched)">Input valid</mdb-success>
                </div>
              </form>
              <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
              <button mdbBtn size="sm" color="secondary" (click)="stepper.previous()">BACK</button>
            </mdb-step>
            <mdb-step name="Step 3" label="Step 3 label">
              <p class="pl-2">Finish!</p>
              <div class="step-actions">
                <button mdbBtn  size="sm" color="primary" (click)="onSubmit()">SUBMIT</button>
              </div>
            </mdb-step>
        </mdb-stepper>

      

          import { Component, OnInit } from '@angular/core';
          import { FormGroup, FormControl, Validators } from '@angular/forms';

          @Component({
            selector: 'vertical-stepper',
            templateUrl: './vertical-stepper.component.html',
          })
          export class VerticalStepperComponent implements OnInit {
            firstFormGroup: FormGroup;
            secondFormGroup: FormGroup;

            ngOnInit() {
              this.firstFormGroup = new FormGroup({
                email: new FormControl('', [Validators.required, Validators.email])
              });
              this.secondFormGroup = new FormGroup({
                password: new FormControl('', Validators.required)
              });
            }

            get email() { return this.firstFormGroup.get('email'); }
            get password() { return this.secondFormGroup.get('password'); }

            onSubmit() {
              // do something here
            }

          }
      

Stepper with shadow MDB Pro component

  • Step 1
  • Step 2
  • Step 3
    Finish!


          <div class="z-depth-1 m-2">
              <div class="div p-4">
                <mdb-stepper #stepper [vertical]="true">
                  <mdb-step name="Step 1" label="Type something" [stepForm]="firstFormGroup">
                    <form [formGroup]="firstFormGroup">
                      <div class="md-form">
                        <input type="text" class="form-control" mdbInput mdbValidate formControlName="email">
                        <label for="">Email</label>
                        <mdb-error *ngIf="email.invalid && (email.dirty || email.touched)">Input invalid</mdb-error>
                        <mdb-success *ngIf="email.valid && (email.dirty || email.touched)">Input valid</mdb-success>
                      </div>
                    </form>
                    <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
                  </mdb-step>
                  <mdb-step name="Step 2" [stepForm]="secondFormGroup">
                    <form [formGroup]="secondFormGroup">
                      <div class="md-form">
                        <input type="password" class="form-control" mdbInput mdbValidate formControlName="password">
                        <label for="">Password</label>
                        <mdb-error *ngIf="password.invalid && (password.dirty || password.touched)">Input invalid</mdb-error>
                        <mdb-success *ngIf="password.valid && (password.dirty || password.touched)">Input valid</mdb-success>
                      </div>
                    </form>
                    <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
                    <button mdbBtn size="sm" color="secondary" (click)="stepper.previous()">BACK</button>
                  </mdb-step>
                  <mdb-step name="Step 3" label="Step 3 label">
                    <p class="pl-2">Finish!</p>
                    <div class="step-actions">
                      <button mdbBtn size="sm" color="primary" (click)="onSubmit()">SUBMIT</button>
                    </div>
                  </mdb-step>
                </mdb-stepper>
              </div>
            </div>
      


          import { Component, OnInit } from '@angular/core';
          import { FormGroup, FormControl, Validators } from '@angular/forms';

          @Component({
            selector: 'stepper-with-shadow',
            templateUrl: './stepper-with-shadow.component.html',
          })
          export class StepperWithShadowComponent implements OnInit {
            firstFormGroup: FormGroup;
            secondFormGroup: FormGroup;

            ngOnInit() {
              this.firstFormGroup = new FormGroup({
                email: new FormControl('', [Validators.required, Validators.email])
              });
              this.secondFormGroup = new FormGroup({
                password: new FormControl('', Validators.required)
              });
            }

            get email() { return this.firstFormGroup.get('email'); }
            get password() { return this.secondFormGroup.get('password'); }

            onSubmit() {
              // do something here
            }

          }
      

Stepper with icon MDB Pro component

  • Step 1
  • Step 2
  • Step 3
    Finish!


        <mdb-stepper #stepper [linear]="true">
          <mdb-step name="Step 1" [stepForm]="firstFormGroup" class="step1">
            <form [formGroup]="firstFormGroup">
              <div class="md-form">
                <input type="text" class="form-control" mdbInput mdbValidate formControlName="email">
                <label for="">Email</label>
                <mdb-error *ngIf="email.invalid && (email.dirty || email.touched)">Input invalid</mdb-error>
                <mdb-success *ngIf="email.valid && (email.dirty || email.touched)">Input valid</mdb-success>
              </div>
            </form>
            <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
          </mdb-step>
          <mdb-step name="Step 2" [stepForm]="secondFormGroup" class="step2">
            <form [formGroup]="secondFormGroup">
              <div class="md-form">
                <input type="password" class="form-control" mdbInput mdbValidate formControlName="password">
                <label for="">Password</label>
                <mdb-error *ngIf="password.invalid && (password.dirty || password.touched)">Input invalid</mdb-error>
                <mdb-success *ngIf="password.valid && (password.dirty || password.touched)">Input valid</mdb-success>
              </div>
            </form>
            <button mdbBtn size="sm" color="primary" (click)="stepper.next()">CONTINUE</button>
            <button mdbBtn size="sm" color="secondary" (click)="stepper.previous()">BACK</button>
          </mdb-step>
          <mdb-step name="Step 3" label="Step 3 label" class="step3">
            <p class="pl-2">Finish!</p>
            <div class="step-actions">
              <button mdbBtn  size="sm" color="primary" (click)="onSubmit()">SUBMIT</button>
            </div>
          </mdb-step>
        </mdb-stepper>


      


        import { Component, OnInit } from '@angular/core';
        import { FormGroup, FormControl, Validators } from '@angular/forms';

        @Component({
          selector: 'stepper-with-icon',
          templateUrl: './stepper-with-icon.component.html',
        })
        export class SteppersWithIcons implements OnInit {
          firstFormGroup: FormGroup;
          secondFormGroup: FormGroup;

          ngOnInit() {
            this.firstFormGroup = new FormGroup({
              email: new FormControl('', [Validators.required, Validators.email])
            });
            this.secondFormGroup = new FormGroup({
              password: new FormControl('', Validators.required)
            });
          }

          get email() { return this.firstFormGroup.get('email'); }
          get password() { return this.secondFormGroup.get('password'); }

          onSubmit() {
            // do something here
          }

        }
      

        ul.stepper.horizontal .step .step-title::before {
          font-weight: 900;
          font-family: "Font Awesome 5 Free";
        }

        ul.stepper.horizontal .step:nth-of-type(1) .step-title {
          &:before {
            content: "\f007";
          }
        }

        ul.stepper.horizontal .step:nth-of-type(2) .step-title {
          &:before {
            content: "\f004";
          }
        }

        ul.stepper.horizontal .step:nth-of-type(3) .step-title {
          &:before {
            content: "\f005";
          }
        }

      

Angular Steppers - API

In this section you will find informations about required modules and available inputs of stepper component.


Modules used

In order to speed up your application, you can choose to import only the modules you actually need, instead of importing the entire MDB Angular library. Remember that importing the entire library, and immediately afterwards a specific module, is bad practice, and can cause application errors.

// MDB Angular Pro
import { StepperModule, WavesModule } from 'ng-uikit-pro-standard'
// MDB Angular Free
import { WavesModule } from 'angular-bootstrap-md'

Components

MdbStepper

Selector: mdb-stepper

Type: MdbStepperComponent

MdbStep

Selector: mdb-step

Type: MdbStepComponent


Inputs

MdbStepper
Name Type Default Description Example
disableWaves boolean false Allow to toggle waves effects [disableWaves]="true"
linear boolean false Allow to toggle linear mode [linear]="true"
vertical boolean false Allow to change stepper orientation to vertical [vertical]="true"
MdbStep
Name Type Default Description Example
editable boolean false Allow to disable edition of finished step [editable]="true"
name string - Allow to add title for specific step [name]="'Step title'"
label string - Allow to add label text for specific step [label]="'Step label'"
stepForm FormGroup - Allow to assign FormGroup element to specific step (used for validation) [stepForm]="fromGroupName"

Methods

You can get access to stepper methods from another component. Add template reference variable to your mdb-stepper component in HTML file

<mdb-stepper #stepper></mdb-stepper>

Then in your typescript file use @ViewChild decorator to get access to MdbStepper methods

@ViewChild('stepper', { static: true }) stepper: MdbStepperComponent

MdbStepper
Name Description Example
next Allow to set next step as active this.stepper.next()
previous Allow to set previous step as active this.stepper.previous()
setNewActiveStep(index: number) Allow to set active state on the step with specified index this.stepper.setNewActiveStep(1)
resetAll Allow to reset all steps and set first step as active this.stepper.resetAll()