Vue Stepper - Getting Started
jQuery
Angular
Vue
React
Stepper is a UI component that allows users to navigate multi-step forms and processes such as checkouts, set-up wizards, and sign-up forms.
This tutorial guides you through the following steps:
- Add a Stepper to a page.
- Configure the component's core settings.
- Create six steps and specify their icons, labels, and other options.
- Disable completed steps as a user progresses.
Each section in this tutorial covers a single configuration step. You can find the complete source code in the following GitHub repository:
Create Stepper
jQuery
Add DevExtreme to your jQuery application and use the code below to create a Stepper component with one step. This example utilizes the items[] array, but you can use dataSource to define steps as well. If you do not specify at least one step, Stepper does not display any data.
$(function() {
    $("#stepper").dxStepper({
        items: [
            {}
        ]
    });
});
<html>
    <head>
        <!-- ... -->
        <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
        <link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/25.1.6/css/dx.light.css">
        <script type="text/javascript" src="https://cdn3.devexpress.com/jslib/25.1.6/js/dx.all.js"></script>
        <script type="text/javascript" src="index.js"></script>
    </head>
    <body>
        <div id="stepper"></div>
    </body>
</html>Angular
Add DevExtreme to your Angular application and use the code below to create a Stepper component with one step. This example utilizes the items[] array, but you can use dataSource to define steps as well. If you do not specify at least one step, Stepper will display no data.
<dx-stepper
    [items]="steps">
</dx-stepper>
import { Component } from '@angular/core';
import { DxStepperTypes } from 'devextreme-angular/ui/stepper';
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    steps: DxStepperTypes.Item[] = [
        {}
    ]
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { DxStepperModule } from 'devextreme-angular';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        AppRoutingModule,
        DxStepperModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }Vue
Add DevExtreme to your Vue application and use the code below to create a Stepper component with one step. This example utilizes the items[] array, but you can use dataSource to define steps as well. If you do not specify at least one step, Stepper will display no data.
<script setup lang="ts">
    import { reactive } from 'vue';
    import { DxStepper, DxItem, DxStepperTypes } from 'devextreme-vue/stepper';
    import 'devextreme/dist/css/dx.light.css';
    const items: DxStepperTypes.Item[] = reactive([
        {}
    ]);
</script>
<template>
    <DxStepper ref="stepperRef">
        <DxItem
            v-for="(item, index) in items"
            :key="index"
        />
    </DxStepper>
</template>React
Add DevExtreme to your React application and use the code below to create a Stepper component with one step. This example utilizes the items[] array, but you can use dataSource to define steps as well. If you do not specify at least one step, Stepper will display no data.
import React, { JSX, useState } from 'react';
import { Stepper, Item, StepperTypes } from 'devextreme-react/stepper';
import 'devextreme/dist/css/dx.light.css';
export default function App(): JSX.Element {
    const [steps, setSteps] = useState<any[]>([
        {}
    ]);
    return (
        <Stepper>
            {
                steps.map((item, index) => (
                    <Item key={index} {...item} />
                ))
            }
        </Stepper>
    );
}Configure Steps
This tutorial specifies the following properties to configure Stepper steps:
- label
 Assigns a step label.
- icon
 Defines a step icon. For more information on the DevExteme icon library, refer to DevExtreme Icons.
- optional
 Adds an "Optional" caption.
You can also specify the following properties:
- isValid
 Indicates input validation state for a step.
- text
 Defines text displayed on a step indicator.
- hint
 Specifies step hint text that appears upon hover or long-press.
- disabled
 Disables a step.
The code below assigns six steps to the component with different configuration options.
jQuery
$(function() {
    $("#stepper").dxStepper({
        items: [{
            label: 'Personal Details'
        }, {
            label: 'Program Selection',
            icon: 'detailslayout'
        }, {
            label: 'Campus and Start Dates',
            icon: 'map'
        }, {
            label: 'Supporting Documents',
            icon: 'textdocument'
        }, {
            label: 'Scholarship and Aid',
            icon: 'money',
            optional: true
        }, {
            label: 'Review and Submit',
            icon: 'send'
        }]
    });
});Angular
// ...
@Component({
    // ...
})
export class AppComponent {
    steps: DxStepperTypes.Item[] = [
        { label: 'Personal Details' },
        { label: 'Program Selection', icon: 'detailslayout' },
        { label: 'Campus and Start Dates', icon: 'map' },
        { label: 'Supporting Documents', icon: 'textdocument' },
        { label: 'Scholarship and Aid', icon: 'money', optional: true },
        { label: 'Review and Submit', icon: 'send' }
    ];
}Vue
<script setup lang="ts">
    // ...
    const items: DxStepperTypes.Item[] = reactive([
        { label: 'Personal Details' },
        { label: 'Program Selection', icon: 'detailslayout' },
        { label: 'Campus and Start Dates', icon: 'map' },
        { label: 'Supporting Documents', icon: 'textdocument' },
        { label: 'Scholarship and Aid', icon: 'money', optional: true },
        { label: 'Review and Submit', icon: 'send' }
    ]);
</script>
<template>
    // ...
</template>React
// ...
export default function App(): JSX.Element {
    const [steps, setSteps] = useState<any[]>([
        { label: 'Personal Details' },
        { label: 'Program Selection', icon: 'detailslayout' },
        { label: 'Campus and Start Dates', icon: 'map' },
        { label: 'Supporting Documents', icon: 'textdocument' },
        { label: 'Scholarship and Aid', icon: 'money', optional: true },
        { label: 'Review and Submit', icon: 'send' },
    ]);
    return (
        // ...
    );
}Customize Steps
Specify items[].template to customize an individual step, or itemTemplate to customize all steps in the component. This tutorial replaces the first step indicator with a star.
For instructions on how to define item templates, refer to Object Structures - template.
jQuery
$(function() {
    $("#stepper").dxStepper({
        items: [{
            label: 'Personal Details',
            template: (data) => `
                <div class='star dx-step-indicator'></div>
                <div class='dx-step-caption'>
                    <div class='dx-step-label'>${data.label}</div>
                </div>
            `,
        }, 
        // ...
        ]
    });
});
.star { 
    aspect-ratio: 1;
    clip-path: polygon(50% 0,79% 90%,2% 35%,98% 35%,21% 90%); 
    box-shadow: 0 0 0 8px #fafafa;
}Angular
<dx-stepper
    [items]="steps"
>
    <div *dxTemplate="let data of 'starTemplate'">
        <div class="star dx-step-indicator"></div>
        <div class="dx-step-caption">
            <div class="dx-step-label">{{ data.label }}</div>
        </div>
    </div>
</dx-stepper>
// ...
@Component({
    // ...
})
export class AppComponent {
    steps: DxStepperTypes.Item[] = [
        { label: 'Personal Details', template: 'starTemplate' },
        // ...
    ];
}
.star { 
    aspect-ratio: 1;
    clip-path: polygon(50% 0,79% 90%,2% 35%,98% 35%,21% 90%); 
    box-shadow: 0 0 0 8px #fafafa;
}Vue
<script setup lang="ts">
    // ...
    const items: DxStepperTypes.Item[] = reactive([
        { label: 'Personal Details', template: 'star' },
        // ...
    ]);
</script>
<template>
    <DxStepper ref="stepperRef" @selection-changed="onSelectionChanged">
        <DxItem
            v-for="(item, index) in items"
            :key="index"
            v-bind="item"
            :template="item.template"
        />
        <template #star="{ data }">
            <div class="star dx-step-indicator"></div>
            <div class="dx-step-caption">
                <div class="dx-step-label">{{ data.label }}</div>
            </div>
        </template>
    </DxStepper>
</template>
<style>
    .star { 
        aspect-ratio: 1;
        clip-path: polygon(50% 0,79% 90%,2% 35%,98% 35%,21% 90%); 
        box-shadow: 0 0 0 8px #fafafa;
    }
</style>React
// ...
export default function App(): JSX.Element {
    function renderStarTemplate(data: StepperTypes.Item): JSX.Element {
        return (
            <React.Fragment>
                <div className="star dx-step-indicator"></div>
                <div className="dx-step-caption">
                <div className="dx-step-label">{data.label}</div>
                </div>
            </React.Fragment>
        );
    }
    const [steps, setSteps] = useState<any[]>([
        { label: 'Personal Details', render: renderStarTemplate },
        // ...
    ]);
    return (
        // ...
    );
}
.star { 
    aspect-ratio: 1;
    clip-path: polygon(50% 0,79% 90%,2% 35%,98% 35%,21% 90%); 
    box-shadow: 0 0 0 8px #fafafa;
}Configure Selection
The following Stepper properties allow you to configure selection at runtime:
- onSelectionChanged
 A function that is called after selection has changed.
- onSelectionChanging
 A function that is called before selection changes.
- selectedIndex
 The selected item index.
- selectedItem
 The selected item object.
This tutorial uses onSelectionChanged to disable steps as users move through the component.
jQuery
$(function() {
    $("#stepper").dxStepper({
        // ...
        onSelectionChanged: ({ component, addedItems }) => {
            const items = component.option("items");
            const newIndex = items.findIndex(item => addedItems[0].label === item.label);
            component.option(`items[${newIndex - 1}].disabled`, true);
        },
    });
});Angular
<dx-stepper 
    [items]="steps"
    (onSelectionChanged)="onSelectionChanged($event)">
    // ...
</dx-stepper>
// ...
@Component({
    // ...
})
export class AppComponent {
    onSelectionChanged(e: DxStepperTypes.SelectionChangedEvent): void {
        const newItem = e.addedItems[0];
        const newIndex = this.steps.findIndex(item => item.label === newItem.label);
        if (newIndex > 0 && !this.steps[newIndex - 1].disabled) {
            this.steps[newIndex - 1].disabled = true;
        }
    }
}Vue
<script setup lang="ts">
    // ...
    const onSelectionChanged = (e: DxStepperTypes.SelectionChangedEvent) => {
        const newItem = e.addedItems[0];
        const newIndex = items.findIndex((item) => item.label === newItem.label);
        if (newIndex > 0) {
            items[newIndex - 1].disabled = true;
        }
    };
</script>
<template>
    <DxStepper ref="stepperRef" @selection-changed="onSelectionChanged">
        <!-- ... -->
    </DxStepper>
</template>React
// ...
export default function App(): JSX.Element {
    // ...
    function onSelectionChanged(e: StepperTypes.SelectionChangedEvent): void {
        const newItem = e.addedItems[0];
        const newIndex = steps.findIndex((item) => item.label === newItem.label);
        if (newIndex > 0 && !steps[newIndex - 1].disabled) {
            const updated = [...steps];
            updated[newIndex - 1] = { ...updated[newIndex - 1], disabled: true };
            setSteps(updated);
        }
    }
    return (
        <Stepper onSelectionChanged={onSelectionChanged}>
            // ...
        </Stepper>
    );
}If you have technical questions, please create a support ticket in the DevExpress Support Center.