DevExtreme v26.1 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Angular Stepper - Overview

The DevExtreme Stepper allows you to indicate progress within a multi-step process and allows users to navigate between individual steps. Use our Stepper UI component to implement multi-page navigation in lengthy forms such as store/cart checkout.

To get started with DevExtreme Stepper, refer to the following step-by-step tutorial: Getting Started with Stepper.

Backend API
<div class="stepper-demo"> <div class="widget-container"> <div class="widget-wrapper" [class]="'widget-wrapper-' + orientation"> <div class="stepper-wrapper"> <div id="iconsLabel" class="stepper-label">Icons and Labels</div> <dx-stepper id="icons" [elementAttr]="{ 'aria-labelledby': 'iconsLabel' }" [selectedIndex]="2" [orientation]="orientation" [linear]="navigationMode" [selectOnFocus]="selectOnFocus" [rtlEnabled]="rtlMode" > @for (step of steps; track step) { <dxi-stepper-item [label]="step.label" [icon]="step.icon" [optional]="step.optional" ></dxi-stepper-item> } </dx-stepper> </div> <div class="stepper-wrapper"> <div id="numbersLabel" class="stepper-label">Numbers and Labels</div> <dx-stepper id="numbers" [elementAttr]="{ 'aria-labelledby': 'numbersLabel' }" [selectedIndex]="2" [orientation]="orientation" [linear]="navigationMode" [selectOnFocus]="selectOnFocus" [rtlEnabled]="rtlMode" > @for (step of steps; track step) { <dxi-stepper-item [label]="step.label" [optional]="step.optional" ></dxi-stepper-item> } </dx-stepper> </div> <div class="stepper-wrapper"> <div id="customTextLabel" class="stepper-label">Custom Text</div> <dx-stepper id="customText" [elementAttr]="{ 'aria-labelledby': 'customTextLabel' }" [selectedIndex]="2" [orientation]="orientation" [linear]="navigationMode" [selectOnFocus]="selectOnFocus" [rtlEnabled]="rtlMode" > @for (step of steps; track step) { <dxi-stepper-item [text]="step.text"></dxi-stepper-item> } </dx-stepper> </div> </div> </div> <div class="options"> <div class="caption">Options</div> <div class="option"> <div>Orientation</div> <dx-button-group id="orientation" keyExpr="value" [items]="orientations" [selectedItemKeys]="[orientation]" (onItemClick)="onOrientationClick($event)" /> </div> <div class="option"> <div>Navigation Mode</div> <dx-button-group id="navigationMode" keyExpr="value" [items]="navigationModes" [selectedItemKeys]="[navigationMode]" (onItemClick)="onNavigationModeClick($event)" /> </div> <div class="option-separator"></div> <div class="option"> <dx-check-box id="selectOnFocus" text="Select step on focus" [value]="selectOnFocus" (onValueChanged)="onSelectOnFocusChanged($event)" /> </div> <div class="option"> <dx-check-box id="rtlMode" text="Right-to-left mode" [value]="rtlMode" (onValueChanged)="onRtlModeChanged($event)" /> </div> </div> </div>
import { bootstrapApplication } from '@angular/platform-browser'; import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core'; import { DxButtonGroupModule, type DxButtonGroupTypes } from 'devextreme-angular/ui/button-group'; import { DxCheckBoxModule, type DxCheckBoxTypes } from 'devextreme-angular/ui/check-box'; import { DxStepperModule, type DxStepperTypes } from 'devextreme-angular/ui/stepper'; import { AppService } from './app.service'; if (!/localhost/.test(document.location.host)) { enableProdMode(); } @Component({ selector: 'demo-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [ DxStepperModule, DxButtonGroupModule, DxCheckBoxModule, ], }) export class AppComponent { steps: DxStepperTypes.Item[]; orientations: any[]; navigationModes: any[]; orientation: string; navigationMode: boolean; selectOnFocus: boolean = true; rtlMode: boolean = false; constructor(private readonly appService: AppService) { this.steps = this.appService.getSteps(); this.orientations = this.appService.getOrientations(); this.navigationModes = this.appService.getNavigationModes(); this.orientation = this.orientations[0].value; this.navigationMode = this.navigationModes[0].value; } onOrientationClick(e: DxButtonGroupTypes.ItemClickEvent) { this.orientation = e.itemData.value; } onNavigationModeClick(e: DxButtonGroupTypes.ItemClickEvent) { this.navigationMode = e.itemData.value; } onSelectOnFocusChanged(e: DxCheckBoxTypes.ValueChangedEvent) { this.selectOnFocus = e.value; } onRtlModeChanged(e: DxCheckBoxTypes.ValueChangedEvent) { this.rtlMode = e.value; } } bootstrapApplication(AppComponent, { providers: [ provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }), AppService, ], });
::ng-deep demo-app { display: flex; flex-direction: column; } ::ng-deep .stepper-demo { display: flex; height: 580px; gap: 20px; } ::ng-deep .widget-container { display: flex; align-items: center; justify-content: center; width: calc(100% - 280px); min-width: 320px; overflow: clip; gap: 20px; } ::ng-deep .widget-wrapper { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; row-gap: 80px; width: 100%; height: 100%; } ::ng-deep .widget-wrapper-vertical { display: flex; flex-direction: row; justify-content: space-around; } ::ng-deep .widget-wrapper-vertical .stepper-wrapper { width: auto; max-width: 33%; } ::ng-deep .widget-wrapper-vertical .stepper-label { text-align: center; white-space: nowrap; } ::ng-deep .widget-wrapper-vertical #customText { width: auto; } ::ng-deep .dx-stepper-vertical { height: 400px; width: 100%; } ::ng-deep .stepper-wrapper { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 16px; } ::ng-deep .stepper-label { font-weight: 600; } ::ng-deep .options { display: flex; flex-direction: column; flex-shrink: 0; width: 300px; box-sizing: border-box; padding: 20px; background-color: rgba(191, 191, 191, 0.15); gap: 16px; height: 100%; } ::ng-deep .caption { font-weight: 500; font-size: 18px; } ::ng-deep .option { display: flex; flex-direction: column; row-gap: 4px; } ::ng-deep .option-separator { border-bottom: 1px solid var(--dx-color-border); } ::ng-deep .dx-buttongroup .dx-button { width: 50%; }
import { Injectable } from "@angular/core"; import { type DxStepperTypes } from 'devextreme-angular/ui/stepper'; @Injectable({ providedIn: "root", }) export class AppService { steps: DxStepperTypes.Item[] = []; orientations = []; navigationModes = []; constructor() { this.steps = [ { text: "A", label: "Cart", icon: "cart", }, { text: "B", label: "Shipping Info", icon: "clipboardtasklist", }, { text: "C", label: "Promo Code", icon: "gift", optional: true, }, { text: "D", label: "Checkout", icon: "packagebox", }, { text: "E", label: "Ordered", icon: "checkmarkcircle", }, ]; this.orientations = [ { text: "Horizontal", value: "horizontal" }, { text: "Vertical", value: "vertical" }, ]; this.navigationModes = [ { text: 'Non-linear', value: false }, { text: 'Linear', value: true }, ]; } getSteps(): DxStepperTypes.Item[] { return this.steps; } getOrientations() { return this.orientations; } getNavigationModes() { return this.navigationModes; } }
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/26.1.5/css/dx.light.css" /> </head> <body class="dx-viewport"> <div class="demo-container"> <demo-app>Loading...</demo-app> </div> <script src="https://cdn.jsdelivr.net/npm/zone.js@0.16.2/bundles/zone.umd.js"></script> <script src="./bundle.js" type="module"></script> </body> </html>

Component Configuration

The following settings are available to you:

  • orientation (default: horizontal)
    Stepper orientation (horizontal or vertical).

  • linear (default: true)
    Specifies whether users must navigate the Stepper sequentially or can skip steps.

  • selectOnFocus (default: true)
    Specifies whether steps focused with keyboard navigation are selected automatically.

  • rtlEnabled (default: false)
    Switches the Stepper to Right-to-Left mode.

Step Settings

To add steps, populate the items collection or specify a dataSource.

Use the following properties to customize steps:

  • text
    Indicator text. If you do not define this option, Stepper numbers steps sequentially.

  • icon
    Indicator icon. Stepper prioritizes icons over the text property.

  • label
    Step caption displayed next to the indicator.

  • optional
    Adds an (Optional) label to the step.

  • isValid
    Allows you to indicate step-related validation errors.

  • disabled
    Deactivates the step.

  • hint
    Tooltip text for the step.

  • template
    Allows you to customize step-related appearance. This property overrides all other step settings.