Backend API
<div class="widget-container">
<dx-resizable
class="resizable-container"
[minWidth]="500"
[minHeight]="150"
[maxHeight]="370"
handles="right"
area=".widget-container"
>
<dx-toolbar #toolbar [multiline]="true">
<dxi-item location="before" widget="dxButton">
<div *dxTemplate>
<dx-button
icon="undo"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Undo')"
></dx-button>
</div>
</dxi-item>
<dxi-item location="before" widget="dxButton">
<div *dxTemplate>
<dx-button
icon="redo"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Redo')"
></dx-button>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
menuItemTemplate="menuSeparatorTemplate"
>
<div *dxTemplate>
<div class="toolbar-separator"></div>
</div>
</dxi-item>
<dxi-item location="before" locateInMenu="auto" widget="dxDropDownButton">
<div *dxTemplate>
<dx-drop-down-button
width="100%"
displayExpr="text"
keyExpr="size"
itemTemplate="fontSizeTemplate"
[stylingMode]="stylingMode"
[items]="fontSizes"
[selectedItemKey]="fontSizes[2].size"
[useSelectMode]="true"
(onSelectionChanged)="onSelectionChanged('Font Size')"
>
<div *dxTemplate="let data of 'fontSizeTemplate'">
<div [style.fontSize]="data.size + 'px'">{{ data.text }}</div>
</div>
</dx-drop-down-button>
</div>
</dxi-item>
<dxi-item location="before" locateInMenu="auto" widget="dxDropDownButton">
<div *dxTemplate>
<dx-drop-down-button
width="100%"
icon="indent"
displayExpr="text"
keyExpr="lineHeight"
[stylingMode]="stylingMode"
[items]="lineHeights"
[useSelectMode]="true"
[selectedItemKey]="lineHeight"
(onSelectionChanged)="onSelectionChanged('Line Height')"
></dx-drop-down-button>
</div>
</dxi-item>
<dxi-item location="before" locateInMenu="auto" widget="dxSelectBox">
<div *dxTemplate>
<dx-select-box
placeholder="Font"
displayExpr="text"
[inputAttr]="{ 'aria-label': 'Font' }"
[items]="fontFamilies"
(onItemClick)="onFontFamilyClick()"
></dx-select-box>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
menuItemTemplate="menuSeparatorTemplate"
>
<div *dxTemplate>
<div class="toolbar-separator"></div>
</div>
</dxi-item>
<dxi-item location="before" widget="dxButtonGroup">
<div *dxTemplate>
<dx-button-group
displayExpr="text"
keyExpr="icon"
stylingMode="outlined"
selectionMode="multiple"
[items]="fontStyles"
(onItemClick)="onButtonClick($event.itemData.hint)"
></dx-button-group>
</div>
</dxi-item>
<dxi-item location="before">
<div *dxTemplate>
<div class="toolbar-separator"></div>
</div>
</dxi-item>
<dxi-item
widget="dxButtonGroup"
location="before"
locateInMenu="auto"
menuItemTemplate="menuTextAlignTemplate"
>
<div *dxTemplate>
<dx-button-group
keyExpr="alignment"
stylingMode="outlined"
[items]="textAlignItems"
[(selectedItemKeys)]="selectedTextAlign"
(onItemClick)="onTextAlignChanged($event)"
></dx-button-group>
</div>
</dxi-item>
<dxi-item location="before" widget="dxButtonGroup">
<div *dxTemplate>
<dx-button-group
keyExpr="alignment"
stylingMode="outlined"
[items]="listTypes"
(onItemClick)="onButtonClick($event.itemData.hint)"
></dx-button-group>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
menuItemTemplate="menuSeparatorTemplate"
>
<div *dxTemplate>
<div class="toolbar-separator"></div>
</div>
</dxi-item>
<dxi-item location="before" locateInMenu="auto" widget="dxSelectBox">
<div *dxTemplate>
<dx-select-box
displayExpr="text"
valueExpr="text"
[inputAttr]="{ 'aria-label': 'Text Style' }"
[value]="heading"
[items]="headings"
(onItemClick)="onHeadingClick()"
></dx-select-box>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
menuItemTemplate="menuSeparatorTemplate"
>
<div *dxTemplate>
<div class="toolbar-separator"></div>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
widget="dxButton"
showText="inMenu"
>
<div *dxTemplate>
<dx-button
icon="link"
text="Link"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Link')"
></dx-button>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
widget="dxButton"
showText="inMenu"
>
<div *dxTemplate>
<dx-button
icon="image"
text="Add image"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Add Image')"
></dx-button>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
menuItemTemplate="menuSeparatorTemplate"
>
<div *dxTemplate>
<div class="toolbar-separator"></div>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
widget="dxButton"
showText="inMenu"
>
<div *dxTemplate>
<dx-button
icon="clearformat"
text="Clear formating"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Clear Formating')"
></dx-button>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
widget="dxButton"
showText="inMenu"
>
<div *dxTemplate>
<dx-button
icon="codeblock"
text="Code block"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Code Block')"
></dx-button>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
widget="dxButton"
showText="inMenu"
>
<div *dxTemplate>
<dx-button
icon="blockquote"
text="Blockquote"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Blockquote')"
></dx-button>
</div>
</dxi-item>
<dxi-item
location="before"
locateInMenu="auto"
menuItemTemplate="menuSeparatorTemplate"
>
<div *dxTemplate>
<div class="toolbar-separator"></div>
</div>
</dxi-item>
<dxi-item location="after" widget="dxButton" showText="inMenu">
<div *dxTemplate>
<dx-button
icon="attach"
text="Attach"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('Attach')"
></dx-button>
</div>
</dxi-item>
<dxi-item locateInMenu="always" widget="dxButton" showText="inMenu">
<div *dxTemplate>
<dx-button
icon="help"
text="About"
[stylingMode]="stylingMode"
(onClick)="onButtonClick('About')"
></dx-button>
</div>
</dxi-item>
<div *dxTemplate="let data of 'menuSeparatorTemplate'">
<div class="toolbar-menu-separator"></div>
</div>
<div *dxTemplate="let data of 'menuTextAlignTemplate'">
<dx-button-group
keyExpr="alignment"
stylingMode="outlined"
[items]="textAlignItemsExtended"
[selectedItemKeys]="selectedTextAlign"
(onItemClick)="onTextAlignChanged($event)"
></dx-button-group>
</div>
</dx-toolbar>
</dx-resizable>
</div>
<div class="options-container">
<div class="caption">Options</div>
<dx-check-box
[(value)]="toolbar.multiline"
text="Multiline mode"
></dx-check-box>
</div>
import { NgModule, Component, enableProdMode, inject } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import {
DxToolbarModule,
DxSelectBoxModule,
DxTemplateModule,
DxResizableModule,
DxDropDownButtonModule,
DxButtonModule,
DxButtonGroupModule,
DxCheckBoxModule,
} from 'devextreme-angular';
import themes from 'devextreme/ui/themes';
import notify from 'devextreme/ui/notify';
import {
FontFamily,
FontSize,
FontStyle,
Heading,
LineHeight,
ListType,
Service,
TextAlign,
TextAlignExtended,
} from './app.service';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
}
let modulePrefix = '';
// @ts-ignore
if (window && window.config?.packageConfigPaths) {
modulePrefix = '/app';
}
@Component({
selector: 'demo-app',
templateUrl: `app/app.component.html`,
styleUrls: [`app/app.component.css`],
providers: [Service],
})
export class AppComponent {
customService = inject(Service);
stylingMode = !themes.current().startsWith('generic') ? 'text' : undefined;
fontSizes: FontSize[] = this.customService.getFontSizes();
lineHeights: LineHeight[] = this.customService.getLineHeights();
lineHeight: number[] = [this.lineHeights[1].lineHeight];
fontFamilies: FontFamily[] = this.customService.getFontFamilies();
headings: Heading[] = this.customService.getHeadings();
heading = this.headings[0]?.text;
fontStyles: FontStyle[] = this.customService.getFontStyles();
textAlignItems: TextAlign[] = this.customService.getTextAlign();
textAlignItemsExtended: TextAlignExtended[] = this.customService.getTextAlignExtended();
selectedTextAlign = [this.textAlignItems[0]?.alignment];
listTypes: ListType[] = this.customService.getListType();
constructor() {
}
onTextAlignChanged(e: { itemData: { hint: string } }): void {
this.onButtonClick(e.itemData.hint);
}
onButtonClick(name: string) {
notify(`The "${name}" button has been clicked`);
}
onSelectionChanged(name: string) {
notify(`The "${name}" value has been changed`);
}
onFontFamilyClick() {
notify('The "Font Family" value has been changed');
}
onHeadingClick() {
notify('The "Heading" value has been changed');
}
}
@NgModule({
imports: [
BrowserModule,
DxToolbarModule,
DxSelectBoxModule,
DxTemplateModule,
DxResizableModule,
DxDropDownButtonModule,
DxButtonModule,
DxButtonGroupModule,
DxCheckBoxModule,
],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule);
:host {
display: block;
}
::ng-deep .dx-resizable-handle::after {
content: "";
position: absolute;
width: 9px;
height: 36px;
border: none;
border-radius: 50px;
background-color: #fff;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.24);
}
::ng-deep .dx-resizable-handle-right::after {
top: 50%;
right: -5px;
transform: translateY(-50%);
}
::ng-deep .dx-toolbar.dx-toolbar-multiline .dx-toolbar-item {
margin-bottom: 5px;
}
::ng-deep .widget-container {
margin-right: 10px;
}
::ng-deep .resizable-container {
padding: 10px;
height: 300px;
border: 1px dotted #999;
border-radius: 4px;
box-sizing: border-box;
}
.options-container {
margin-top: 20px;
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
position: relative;
}
.caption {
font-size: 18px;
font-weight: 500;
margin-bottom: 10px;
}
::ng-deep .toolbar-separator {
height: 36px;
margin: 0 5px;
border-left: 1px solid #ddd;
}
::ng-deep .toolbar-menu-separator {
height: 1px;
border-bottom: 1px solid #ddd;
}
import { Injectable } from '@angular/core';
export class FontSize {
size: number;
text: string;
}
export class LineHeight {
lineHeight: number;
text: string;
}
export class FontFamily {
text: string;
}
export class Heading {
text: string;
}
export class FontStyle {
icon: string;
hint: string;
}
export class TextAlign {
icon: string;
alignment: string;
hint: string;
}
export class TextAlignExtended extends TextAlign {
text: string;
}
export class ListType {
icon: string;
alignment: string;
hint: string;
}
const fontSizes: FontSize[] = [
{ size: 10, text: '10px' },
{ size: 12, text: '12px' },
{ size: 14, text: '14px' },
{ size: 16, text: '16px' },
{ size: 18, text: '18px' },
];
const lineHeights: LineHeight[] = [
{ lineHeight: 1, text: '1' },
{ lineHeight: 1.35, text: '1.35' },
{ lineHeight: 1.5, text: '1.5' },
{ lineHeight: 2, text: '2' },
];
const fontFamilies: FontFamily[] = [
{ text: 'Arial' },
{ text: 'Courier New' },
{ text: 'Georgia' },
{ text: 'Impact' },
{ text: 'Lucida Console' },
{ text: 'Tahoma' },
{ text: 'Times New Roman' },
];
const headings: Heading[] = [
{ text: 'Normal text' },
{ text: 'Heading 1' },
{ text: 'Heading 2' },
{ text: 'Heading 3' },
{ text: 'Heading 4' },
{ text: 'Heading 5' },
];
const fontStyles: FontStyle[] = [
{
icon: 'bold',
hint: 'Bold',
},
{
icon: 'italic',
hint: 'Italic',
},
{
icon: 'underline',
hint: 'Underlined',
},
{
icon: 'strike',
hint: 'Strikethrough',
},
];
const textAlignsExtended: TextAlignExtended[] = [
{
icon: 'alignleft',
alignment: 'left',
hint: 'Align Left',
text: 'Align left',
},
{
icon: 'aligncenter',
alignment: 'center',
hint: 'Center',
text: 'Center',
},
{
icon: 'alignright',
alignment: 'right',
hint: 'Align Right',
text: 'Align right',
},
{
icon: 'alignjustify',
alignment: 'justify',
hint: 'Justify',
text: 'Justify',
},
];
const listTypes: ListType[] = [
{
icon: 'orderedlist',
alignment: 'orderedlist',
hint: 'Ordered',
},
{
icon: 'bulletlist',
alignment: 'bulletlist',
hint: 'Bullet',
},
];
@Injectable()
export class Service {
getFontSizes(): FontSize[] {
return fontSizes;
}
getLineHeights(): LineHeight[] {
return lineHeights;
}
getFontFamilies(): FontFamily[] {
return fontFamilies;
}
getHeadings(): Heading[] {
return headings;
}
getFontStyles(): FontStyle[] {
return fontStyles;
}
getTextAlign(): TextAlign[] {
return textAlignsExtended.map(
({ icon, alignment, hint }) => ({ icon, alignment, hint }),
);
}
getTextAlignExtended(): TextAlignExtended[] {
return textAlignsExtended;
}
getListType(): ListType[] {
return listTypes;
}
}
// 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',
'card-view',
'chart',
'chat',
'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',
'pagination',
'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',
'stepper',
'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/animations': {
'esModule': true,
},
'@angular/forms': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://cdn.jsdelivr.net/npm/',
'bundles:': '../../../../bundles/',
'externals:': '../../../../bundles/externals/',
},
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.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@link:../../packages/devextreme/artifacts/npm/devextreme/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.6/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.24',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.64',
/* devextreme-angular umd maps */
'devextreme-angular': 'bundles:devextreme-angular/devextreme-angular.umd.js',
'devextreme-angular/common/ai-integration': 'bundles:devextreme-angular/devextreme-angular-common-ai-integration.umd.js',
'devextreme-angular/core': 'bundles:devextreme-angular/devextreme-angular-core.umd.js',
'devextreme-angular/common/charts': 'bundles:devextreme-angular/devextreme-angular-common-charts.umd.js',
'devextreme-angular/common/core/animation': 'bundles:devextreme-angular/devextreme-angular-common-core-animation.umd.js',
'devextreme-angular/common/core/environment': 'bundles:devextreme-angular/devextreme-angular-common-core-environment.umd.js',
'devextreme-angular/common/core/events': 'bundles:devextreme-angular/devextreme-angular-common-core-events.umd.js',
'devextreme-angular/common/core/localization': 'bundles:devextreme-angular/devextreme-angular-common-core-localization.umd.js',
'devextreme-angular/common/core': 'bundles:devextreme-angular/devextreme-angular-common-core.umd.js',
'devextreme-angular/common/data/custom-store': 'bundles:devextreme-angular/devextreme-angular-common-data-custom-store.umd.js',
'devextreme-angular/common/data': 'bundles:devextreme-angular/devextreme-angular-common-data.umd.js',
'devextreme-angular/common/export/excel': 'bundles:devextreme-angular/devextreme-angular-common-export-excel.umd.js',
'devextreme-angular/common/export/pdf': 'bundles:devextreme-angular/devextreme-angular-common-export-pdf.umd.js',
'devextreme-angular/common/export': 'bundles:devextreme-angular/devextreme-angular-common-export.umd.js',
'devextreme-angular/common/grids': 'bundles:devextreme-angular/devextreme-angular-common-grids.umd.js',
'devextreme-angular/common': 'bundles:devextreme-angular/devextreme-angular-common.umd.js',
'devextreme-angular/http': 'bundles:devextreme-angular/devextreme-angular-http.umd.js',
'devextreme-angular/core/tokens': 'bundles:devextreme-angular/devextreme-angular-core-tokens.umd.js',
...componentNames.reduce((acc, name) => {
acc[`devextreme-angular/ui/${name}`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}.umd.js`;
acc[`devextreme-angular/ui/${name}/nested`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}-nested.umd.js`;
return acc;
}, {}),
'tslib': 'npm:tslib/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@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'inferno': 'npm:inferno@8.2.3/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@8.2.3/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/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',
'@preact/signals-core': 'npm:@preact/signals-core@1.8.0/dist/signals-core.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/common/core/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:rxjs@7.5.3/package.json',
'npm:rxjs@7.5.3/operators/package.json',
'npm:devexpress-diagram@2.2.24/package.json',
'npm:devexpress-gantt@4.1.64/package.json',
],
};
System.config(window.config);
// System.import('@angular/compiler').catch(console.error.bind(console));
// eslint-disable-next-line
const useTgzInCSB = ['openai'];
let packagesInfo = {
"@angular/core": {
"version": "17.3.12"
},
"core-js": {
"version": "2.6.12"
},
"typescript": {
"version": "5.4.5"
},
"zone.js": {
"version": "0.14.10"
}
};
<!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/25.1.7/css/dx.light.css" />
<script src="https://cdn.jsdelivr.net/npm/core-js@2.6.12/client/shim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/zone.js@0.14.10/bundles/zone.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/reflect-metadata@0.1.13/Reflect.js"></script>
<script src="https://cdn.jsdelivr.net/npm/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>
In this demo, you can drag our Toolbar container's resizing handle to visualize resize operations and view our rendering implementation on different screens. When used in single-line mode (default), our Toolbar does not wrap content and displays an overflow menu for items that do not fit within the container. Use the locateInMenu property to control whether items appear in the overflow menu.
If Toolbar width exceeds container width (and if you enable the component’s multiline property), our Toolbar wraps content across multiple lines.