DevExtreme v24.1 is now available.

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

Your search did not match any results.

Angular Navigation - Right-to-Left Support

The DevExtreme Navigation components support right-to-left (RTL) languages. The components can display content in a right-to-left direction and mirror associated UI elements.

Backend API
<div [ngClass]="{ 'dx-rtl': rtlEnabled }"> <div class="options"> <div class="caption">Options</div> <div class="dx-fieldset"> <div class="dx-field"> <div class="dx-field-label">Language</div> <div class="dx-field-value"> <dx-select-box [items]="languages" [inputAttr]="{ 'aria-label': 'Language' }" [value]="languages[1]" (onValueChanged)="selectLanguage($event)" ></dx-select-box> </div> </div> </div> </div> <div> <div class="dx-fieldset"> <div class="dx-fieldset-header"> <dx-menu [dataSource]="continents" [rtlEnabled]="rtlEnabled" [displayExpr]="rtlEnabled ? 'textAr' : 'text'" ></dx-menu> </div> </div> <div class="dx-fieldset"> <div class="dx-field"> <div class="dx-field-label"> <dx-tree-view [width]="200" [dataSource]="continents" [displayExpr]="rtlEnabled ? 'textAr' : 'text'" [rtlEnabled]="rtlEnabled" ></dx-tree-view> </div> <div class="dx-field-value"> <dx-accordion [dataSource]="europeCountries" [rtlEnabled]="rtlEnabled" [itemTitleTemplate]="rtlEnabled ? 'arabicTitle' : 'englishTitle'" [itemTemplate]="rtlEnabled ? 'arabic' : 'english'" > <div *dxTemplate="let item of 'arabicTitle'"> {{ item.nameAr }} </div> <div *dxTemplate="let country of 'arabic'"> <div>عاصمة: {{ country.capitalAr }} </div> <div>عدد السكان: {{ country.population }} نسمة</div> <div>المساحة: {{ country.area }} كم<sup>2</sup></div> </div> <div *dxTemplate="let item of 'englishTitle'"> {{ item.nameEn }} </div> <div *dxTemplate="let country of 'english'"> <div>Capital: {{ country.capitalEn }} </div> <div>Population: {{ country.population }} people</div> <div>Area: {{ country.area }} km<sup>2</sup></div> </div> </dx-accordion> </div> </div> </div> </div> </div>
import { NgModule, Component, enableProdMode } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { DxAccordionModule, DxSelectBoxModule, DxMenuModule, DxTreeViewModule, DxTemplateModule, } from 'devextreme-angular'; import { Continent, EuropeCountry, 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 { continents: Continent[]; europeCountries: EuropeCountry[]; languages: string[] = [ 'Arabic: Right-to-Left direction', 'English: Left-to-Right direction', ]; rtlEnabled = false; constructor(service: Service) { this.continents = service.getContinents(); this.europeCountries = service.getEuropeCountries(); } selectLanguage(e) { this.rtlEnabled = e.value === this.languages[0]; } } @NgModule({ imports: [ BrowserModule, DxAccordionModule, DxSelectBoxModule, DxMenuModule, DxTreeViewModule, DxTemplateModule, ], declarations: [AppComponent], bootstrap: [AppComponent], }) export class AppModule { } platformBrowserDynamic().bootstrapModule(AppModule);
sup { font-size: 0.8em; vertical-align: super; line-height: 0; } .options { padding: 20px; background-color: rgba(191, 191, 191, 0.15); margin-bottom: 20px; } ::ng-deep .options .dx-fieldset { margin: 0; } .caption { font-size: 18px; font-weight: 500; padding-right: 15px; } ::ng-deep .dx-theme-material .dx-accordion .dx-accordion-item-opened .dx-accordion-item-title { padding-top: 20px; }
import { Injectable } from '@angular/core'; export class Continent { id: string; text: string; textAr: string; items?: Continent[]; } export class EuropeCountry { nameAr: string; nameEn: string; population: number; area: number; capitalAr: string; capitalEn: string; } const continents: Continent[] = [{ id: '1', text: 'Africa', textAr: 'أفريقيا', items: [ { id: '1_2', text: 'Ethiopia', textAr: 'أثيوبيا', items: [{ id: '1_2_1', text: 'Addis Ababa', textAr: 'أديس أبابا', }, { id: '1_2_2', text: 'Dire Dawa', textAr: 'دير داوا', }], }, { id: '1_1', text: 'Nigeria', textAr: 'نيجيريا', items: [{ id: '1_1_1', text: 'Lagos', textAr: 'لاغوس', }, { id: '1_1_2', text: 'Kano', textAr: 'كانو', }], }, ], }, { id: '2', text: 'Asia', textAr: 'آسيا', items: [{ id: '2_1', text: 'China', textAr: 'الصين', items: [{ id: '2_1_1', text: 'Beijing', textAr: 'بكين', }, { id: '2_1_2', text: 'Shanghai', textAr: 'شنغهاي', }], }, { id: '2_2', text: 'India', textAr: 'الهند', items: [{ id: '2_2_1', text: 'Indianapolis', textAr: 'انديانابوليس', }, { id: '2_2_2', text: 'New Delhi', textAr: 'نيودلهي', }], }], }, { id: '3', text: 'Australia', textAr: 'أستراليا', items: [{ id: '3_1', text: 'Australia', textAr: 'أستراليا', items: [{ id: '3_1_1', text: 'Canberra', textAr: 'كانبيرا', }, { id: '3_1_2', text: 'Melbourne', textAr: 'ملبورن', }, { id: '3_1_3', text: 'Sydney', textAr: 'سيدني', }], }], }, { id: '4', text: 'Europe', textAr: 'أوروبا', items: [{ id: '4_1', text: 'Germany', textAr: 'ألمانيا', items: [{ id: '4_1_1', text: 'Berlin', textAr: 'البرلينية', }, { id: '4_1_2', text: 'Hamburg', textAr: 'هامبورغ', }], }, { id: '4_2', text: 'Russia', textAr: 'روسيا', items: [{ id: '4_2_1', text: 'Moscow', textAr: 'موسكو', }, { id: '4_2_2', text: 'Saint Petersburg', textAr: 'سانت بطرسبرغ', }], }], }, { id: '5', text: 'North America', textAr: 'أمريكا الشمالية', items: [{ id: '5_2', text: 'Mexico', textAr: 'المكسيك', items: [{ id: '5_2_1', text: 'Mexico City', textAr: 'مكسيكو سيتي', }, { id: '5_2_2', text: 'Guadalajara', textAr: 'غوادالاخارا', }], }, { id: '5_1', text: 'United States', textAr: 'الولايات المتحدة الأمريكية', items: [{ id: '5_1_1', text: 'New York', textAr: 'نيويورك', }, { id: '5_1_2', text: 'Washington', textAr: 'واشنطن', }], }], }, { id: '6', text: 'South America', textAr: 'أمريكا الجنوبية', items: [{ id: '6_1', text: 'Brazil', textAr: 'البرازيل', items: [{ id: '6_1_1', text: 'Brasilia', textAr: 'برازيليا', }, { id: '6_1_2', text: 'Sao Paulo', textAr: 'ساو باولو', }], }, { id: '6_2', text: 'Colombia', textAr: 'كولومبيا', items: [{ id: '6_2_1', text: 'Bogota', textAr: 'بوغوتا', }, { id: '6_2_2', text: 'Medellin', textAr: 'ميديلين', }], }], }]; const europeCountries: EuropeCountry[] = [{ nameAr: 'النمسا', nameEn: 'Austria', population: 8451900, area: 83855.0, capitalEn: 'Vienna', capitalAr: 'فيينا', }, { nameAr: 'بلجيكا', nameEn: 'Belgium', population: 11161600, area: 30528.0, capitalEn: 'Brussels', capitalAr: 'بروكسل', }, { nameAr: 'بلغاريا', nameEn: 'Bulgaria', population: 7284600, area: 110994.0, capitalEn: 'Sofia', capitalAr: 'صوفيا', }, { nameAr: 'كرواتيا', nameEn: 'Croatia', population: 4262100, area: 56594.0, capitalEn: 'Zagreb', capitalAr: 'زغرب', }]; @Injectable() export class Service { getContinents(): Continent[] { return continents; } getEuropeCountries(): EuropeCountry[] { return europeCountries; } }
// 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/ const componentNames = [ 'accordion', 'action-sheet', 'autocomplete', 'bar-gauge', 'box', 'bullet', 'button-group', 'button', 'calendar', 'chart', 'check-box', 'circular-gauge', 'color-box', 'context-menu', 'data-grid', 'date-box', 'date-range-box', 'defer-rendering', 'diagram', 'draggable', 'drawer', 'drop-down-box', 'drop-down-button', 'file-manager', 'file-uploader', 'filter-builder', 'form', 'funnel', 'gallery', 'gantt', 'html-editor', 'linear-gauge', 'list', 'load-indicator', 'load-panel', 'lookup', 'map', 'menu', 'multi-view', 'nested', 'number-box', 'pie-chart', 'pivot-grid-field-chooser', 'pivot-grid', 'polar-chart', 'popover', 'popup', 'progress-bar', 'radio-group', 'range-selector', 'range-slider', 'recurrence-editor', 'resizable', 'responsive-box', 'sankey', 'scheduler', 'scroll-view', 'select-box', 'slider', 'sortable', 'sparkline', 'speed-dial-action', 'splitter', 'switch', 'tab-panel', 'tabs', 'tag-box', 'text-area', 'text-box', 'tile-view', 'toast', 'toolbar', 'tooltip', 'tree-list', 'tree-map', 'tree-view', 'validation-group', 'validation-summary', 'validator', 'vector-map', ]; 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, }, '@angular/platform-browser-dynamic': { 'esModule': true, }, '@angular/platform-browser': { 'esModule': true, }, '@angular/core': { 'esModule': true, }, '@angular/common': { 'esModule': true, }, '@angular/common/http': { 'esModule': true, }, '@angular/compiler': { 'esModule': true, }, '@angular/animations': { 'esModule': true, }, '@angular/forms': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', 'bundles:': '../../../../bundles/', }, map: { 'ts': 'npm:plugin-typescript@4.2.4/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', /* @angular */ '@angular/compiler': 'bundles:@angular/compiler.umd.js', '@angular/platform-browser-dynamic': 'bundles:@angular/platform-browser-dynamic.umd.js', '@angular/core': 'bundles:@angular/core.umd.js', '@angular/core/primitives/signals': 'bundles:@angular/core.primitives.signals.umd.js', '@angular/common': 'bundles:@angular/common.umd.js', '@angular/common/http': 'bundles:@angular/common-http.umd.js', '@angular/platform-browser': 'bundles:@angular/platform-browser.umd.js', '@angular/platform-browser/animations': 'bundles:@angular/platform-browser.umd.js', '@angular/forms': 'bundles:@angular/forms.umd.js', /* devextreme */ 'devextreme': 'npm:devextreme@24.1.6/cjs', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.13', 'devextreme/bundles/dx.all': 'npm:devextreme@24.1.6/bundles/dx.all.js', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.11', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.56', /* devextreme-angular umd maps */ 'devextreme-angular': 'bundles:devextreme-angular/devextreme-angular.umd.js', 'devextreme-angular/core': 'bundles:devextreme-angular/devextreme-angular-core.umd.js', 'devextreme-angular/http': 'bundles:devextreme-angular/devextreme-angular-http.umd.js', ...componentNames.reduce((acc, name) => { acc[`devextreme-angular/ui/${name}`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}.umd.js`; return acc; }, {}), 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'tslib': 'npm:tslib@2.6.1/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', '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.8/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.8/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.13/inferno/package.json', 'npm:rxjs@7.5.3/package.json', 'npm:rxjs@7.5.3/operators/package.json', 'npm:devexpress-diagram@2.2.11/package.json', 'npm:devexpress-gantt@4.1.56/package.json', ], }; System.config(window.config); // System.import('@angular/compiler').catch(console.error.bind(console));
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" 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/24.1.6/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.13.3/bundles/zone.umd.min.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>

To enable RTL language support in the application, you can either set the globalConfig object's rtlEnabled property to true or specify each component's rtlEnabled property individually. Note that individual RTL parameters have higher priority than general parameters.

In this demo, you can use the language drop-down menu (for example, change the language from English to Arabic) to explore the differences between default and RTL modes.