DevExtreme v23.2 is now available.

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

Your search did not match any results.

Overview

The Tabs component allows you to create a tabbed UI to navigate between pages or views. You can create tab items in the items array, or populate tab items from a dataSource.

Customize Tab Contents and Appearance

You can initialize a tab’s contents (text, icons and badges) with values from underlying data objects. This example demonstrates this technique.

Use the drop-down editors on the right to change the component's orientation, styling mode, and icon position.

You can also specify an item template (itemTemplate) to customize tabs.

Configure Overflow Behavior

The Tabs component stretches to fit its container if you do not specify the component's width. When the total tab width exceeds the component’s width, navigation buttons appear. A user can click these buttons to scroll through the tabs. Use the showNavButtons and scrollByContent properties to control this behavior.

Backend API
<div class="tabs-demo"> <div class="widget-container"> <div [ngClass]="widgetWrapperClasses"> <dx-tabs #withText [width]="width" [selectedIndex]="0" [rtlEnabled]="rtlEnabled" [scrollByContent]="scrollByContent" [showNavButtons]="showNavButtons" [dataSource]="tabsWithText" [orientation]="orientation" [stylingMode]="stylingMode" [iconPosition]="iconPosition" ></dx-tabs> <dx-tabs #withIconAndText [width]="width" [selectedIndex]="0" [rtlEnabled]="rtlEnabled" [scrollByContent]="scrollByContent" [showNavButtons]="showNavButtons" [dataSource]="tabsWithIconAndText" [orientation]="orientation" [stylingMode]="stylingMode" [iconPosition]="iconPosition" ></dx-tabs> <dx-tabs #withIcon [width]="width" [selectedIndex]="0" [rtlEnabled]="rtlEnabled" [scrollByContent]="scrollByContent" [showNavButtons]="showNavButtons" [dataSource]="tabsWithIcon" [orientation]="orientation" [stylingMode]="stylingMode" [iconPosition]="iconPosition" ></dx-tabs> </div> </div> <div class="options"> <div class="caption">Options</div> <div class="option"> <span>Orientation</span> <dx-select-box [inputAttr]="{ 'aria-label': 'Orientation' }" [items]="orientations" [(value)]="orientation" (onValueChanged)="onOrientationChanged($event)" ></dx-select-box> </div> <div class="option"> <span>Styling mode</span> <dx-select-box [inputAttr]="{ 'aria-label': 'Styling Mode' }" [items]="stylingModes" [(value)]="stylingMode" ></dx-select-box> </div> <div class="option"> <span>Icon position</span> <dx-select-box [inputAttr]="{ 'aria-label': 'Icon Position' }" [items]="iconPositions" [(value)]="iconPosition" ></dx-select-box> </div> <div class="option"> <dx-check-box id="show-navigation-buttons" text="Show navigation buttons" [(value)]="showNavButtons" (onValueChanged)="toggleStrictWidthClass()" ></dx-check-box> </div> <div class="option"> <dx-check-box text="Scroll content" [(value)]="scrollByContent" (onValueChanged)="toggleStrictWidthClass()" ></dx-check-box> </div> <div class="option"> <dx-check-box text="Full width" [value]="false" (onValueChanged)="onFullWidthChanged($event)" ></dx-check-box> </div> <div class="option"> <dx-check-box text="Right-to-left mode" [(value)]="rtlEnabled" ></dx-check-box> </div> </div> </div>
import { NgModule, Component, enableProdMode, ViewChild, } from '@angular/core'; import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { DxSelectBoxModule, DxSelectBoxTypes } from 'devextreme-angular/ui/select-box'; import { DxCheckBoxModule, DxCheckBoxTypes } from 'devextreme-angular/ui/check-box'; import { DxTabsModule, DxTabsComponent, DxTabsTypes } from 'devextreme-angular/ui/tabs'; import { Tab, Service } from './app.service'; if (!/localhost/.test(document.location.host)) { enableProdMode(); } @Component({ selector: 'demo-app', templateUrl: 'app/app.component.html', styleUrls: ['app/app.component.css'], providers: [Service], }) export class AppComponent { @ViewChild('withText') withText: DxTabsComponent; @ViewChild('withIconAndText') withIconAndText: DxTabsComponent; @ViewChild('withIcon') withIcon: DxTabsComponent; tabsWithText: Tab[]; tabsWithIconAndText: Tab[]; tabsWithIcon: Tab[]; showNavButtons = false; scrollByContent = false; rtlEnabled = false; orientations: DxTabsTypes.Orientation[] = ['horizontal', 'vertical']; stylingModes: DxTabsTypes.TabsStyle[] = ['primary', 'secondary']; iconPositions: DxTabsTypes.TabsIconPosition[] = ['top', 'start', 'end', 'bottom']; width = 'auto'; orientation = this.orientations[0]; stylingMode = this.stylingModes[1]; iconPosition = this.iconPositions[0]; widgetWrapperClasses = { 'widget-wrapper': true, 'widget-wrapper-horizontal': true, 'widget-wrapper-vertical': false, 'strict-width': false, }; constructor(service: Service) { this.tabsWithText = service.getTabsWithText(); this.tabsWithIconAndText = service.getTabsWithIconAndText(); this.tabsWithIcon = service.getTabsWithIcon(); } onOrientationChanged(e: DxSelectBoxTypes.ValueChangedEvent) { if (e.value === 'vertical') { this.widgetWrapperClasses['widget-wrapper-vertical'] = true; this.widgetWrapperClasses['widget-wrapper-horizontal'] = false; } else { this.widgetWrapperClasses['widget-wrapper-horizontal'] = true; this.widgetWrapperClasses['widget-wrapper-vertical'] = false; } } toggleStrictWidthClass() { this.widgetWrapperClasses['strict-width'] = this.scrollByContent || this.showNavButtons; } onFullWidthChanged(e: DxCheckBoxTypes.ValueChangedEvent) { this.width = e.value ? '100%' : 'auto'; } } @NgModule({ imports: [ BrowserModule, BrowserTransferStateModule, DxTabsModule, DxCheckBoxModule, DxSelectBoxModule, ], declarations: [AppComponent], bootstrap: [AppComponent], }) export class AppModule { } platformBrowserDynamic().bootstrapModule(AppModule);
::ng-deep .tabs-demo { display: flex; } ::ng-deep .strict-width { max-width: 340px; } ::ng-deep .dx-theme-generic .strict-width { max-width: 250px; } ::ng-deep .widget-container { display: flex; align-items: center; justify-content: center; flex-grow: 1; width: 100%; min-width: 200px; padding: 16px 32px; overflow: clip; } ::ng-deep .widget-wrapper { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 80px; width: 100%; } ::ng-deep .widget-wrapper-vertical { width: 100%; flex-direction: row; align-items: center; } ::ng-deep .options { display: flex; flex-direction: column; flex-shrink: 0; padding: 20px; background-color: rgba(191, 191, 191, 0.15); } ::ng-deep .caption { font-weight: 500; font-size: 18px; } ::ng-deep #show-navigation-buttons { margin-top: 22px; } ::ng-deep .option { margin-top: 20px; } ::ng-deep .dx-tabs { max-width: 100%; } ::ng-deep .dx-tabs-vertical { height: 216px; } ::ng-deep .dx-viewport:not(.dx-theme-generic) .dx-tabs-horizontal { border-block-end: 1px solid rgb(225, 225, 225, 0.4); } ::ng-deep .dx-viewport:not(.dx-theme-generic) .dx-tabs-vertical { height: 232px; border-inline-end: 1px solid rgb(225, 225, 225, 0.4); }
import { Injectable } from '@angular/core'; export class Tab { id: number; text?: string; icon?: string; } const tabsWithText: Tab[] = [ { id: 0, text: 'User', }, { id: 1, text: 'Analytics', }, { id: 2, text: 'Clients', }, { id: 3, text: 'Orders', }, { id: 4, text: 'Favorites', }, { id: 5, text: 'Search', }, ]; const tabsWithIcon: Tab[] = [ { id: 0, icon: 'user', }, { id: 1, icon: 'chart', }, { id: 2, icon: 'accountbox', }, { id: 3, icon: 'ordersbox', }, { id: 4, icon: 'bookmark', }, { id: 5, icon: 'search', }, ]; const tabsWithIconAndText: Tab[] = [ { id: 0, text: 'User', icon: 'user', }, { id: 1, text: 'Analytics', icon: 'chart', }, { id: 2, text: 'Clients', icon: 'accountbox', }, { id: 3, text: 'Orders', icon: 'ordersbox', }, { id: 4, text: 'Favorites', icon: 'bookmark', }, { id: 5, text: 'Search', icon: 'search', }, ]; @Injectable() export class Service { getTabsWithText(): Tab[] { return tabsWithText; } getTabsWithIconAndText(): Tab[] { return tabsWithIconAndText; } getTabsWithIcon(): Tab[] { return tabsWithIcon; } }
// In real applications, you should not transpile code in the browser. // You can see how to create your own application with Angular and DevExtreme here: // https://js.devexpress.com/Documentation/Guide/Angular_Components/Getting_Started/Create_a_DevExtreme_Application/ window.exports = window.exports || {}; window.config = { transpiler: 'ts', typescriptOptions: { module: 'system', emitDecoratorMetadata: true, experimentalDecorators: true, }, meta: { 'typescript': { 'exports': 'ts', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', }, map: { 'ts': 'npm:plugin-typescript@4.2.4/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', '@angular/core': 'npm:@angular/core@12.2.17', '@angular/platform-browser': 'npm:@angular/platform-browser@12.2.17', '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic@12.2.17', '@angular/forms': 'npm:@angular/forms@12.2.17', '@angular/common': 'npm:@angular/common@12.2.17', '@angular/compiler': 'npm:@angular/compiler@12.2.17', 'tslib': 'npm:tslib@2.6.2/tslib.js', 'rxjs': 'npm:rxjs@7.5.3/dist/bundles/rxjs.umd.js', 'rxjs/operators': 'npm:rxjs@7.5.3/dist/cjs/operators/index.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign@1.1.0', 'devextreme': 'npm:devextreme@23.2.5/cjs', 'devextreme/bundles/dx.all': 'npm:devextreme@23.2.5/bundles/dx.all.js', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.6.4/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.5', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.51', 'devextreme-angular': 'npm:devextreme-angular@23.2.5', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12', 'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js', 'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js', 'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js', 'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js', 'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js', 'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js', 'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js', 'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js', // Prettier 'prettier/standalone': 'npm:prettier@2.8.4/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.4/parser-html.js', }, packages: { 'app': { main: './app.component.ts', defaultExtension: 'ts', }, 'devextreme': { defaultExtension: 'js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, 'rxjs': { defaultExtension: 'js', }, 'rxjs/operators': { defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.12/inferno/package.json', 'npm:@angular/*/package.json', 'npm:@angular/common@12.2.17/*/package.json', 'npm:rxjs@7.5.3/package.json', 'npm:rxjs@7.5.3/operators/package.json', 'npm:devextreme-angular@23.2.5/*/package.json', 'npm:devextreme-angular@23.2.5/ui/*/package.json', 'npm:devextreme-angular@23.2.5/package.json', 'npm:devexpress-diagram@2.2.5/package.json', 'npm:devexpress-gantt@4.1.51/package.json', ], }; System.config(window.config);
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <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=1.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/23.2.5/css/dx.light.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/zone.js@0.12.0/dist/zone.js"></script> <script src="https://unpkg.com/reflect-metadata@0.1.13/Reflect.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script src="config.js"></script> <script> System.import("app").catch(console.error.bind(console)); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <demo-app>Loading...</demo-app> </div> </body> </html>