DevExtreme v24.1 is now available.

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

Your search did not match any results.

Scrolling

This demo shows two implementations of scrolling in the Popup component.

When you click the first Show Popup button, a Popup with a native scrollbar appears. The component always displays a native scrollbar when the height of the Popup's content is greater than that of the Popup.

Backend API
<div class="demo-container"> <div class="button-container"> <dx-button text="Show Popup" type="default" [width]="300" (onClick)="showPopup($event)" > </dx-button> <div class="label"> A native scrollable container </div> </div> <div class="button-container"> <dx-button text="Show Popup" [width]="300" (onClick)="showPopupWithScrollView($event)" > </dx-button> <div class="label"> The ScrollView </div> </div> </div> <dx-popup [width]="360" [height]="320" [hideOnOutsideClick]="true" [showCloseButton]="true" [(visible)]="popupVisible" title="Downtown Inn" > <div *dxTemplate="let data of 'content'"> <div> <div class="caption">Description</div> In the heart of LA's business district, the Downtown Inn has a welcoming staff and award winning restaurants that remain open 24 hours a day. Use our conference room facilities to conduct meetings and have a drink at our beautiful rooftop bar. <br /><br /> <div class="content"> <div> <div class="caption">Features</div> <div>Concierge</div> <div>Restaurant</div> <div>Valet Parking</div> <div>Fitness Center</div> <div>Sauna</div> <div>Airport Shuttle</div> </div> <div> <div class="caption">Rooms</div> <div>Climate control</div> <div>Air conditioning</div> <div>Coffee/tea maker</div> <div>Iron/ironing</div> </div> </div> </div> </div> <dxi-toolbar-item widget="dxButton" toolbar="bottom" location="center" [options]="bookButtonOptions" > </dxi-toolbar-item> </dx-popup> <dx-popup [width]="360" [height]="320" [hideOnOutsideClick]="true" [showCloseButton]="true" [(visible)]="popupWithScrollViewVisible" title="Downtown Inn" > <div *dxTemplate="let data of 'content'"> <dx-scroll-view width="100%" height="100%"> <div class="caption">Description</div> In the heart of LA's business district, the Downtown Inn has a welcoming staff and award winning restaurants that remain open 24 hours a day. Use our conference room facilities to conduct meetings and have a drink at our beautiful rooftop bar. <br /><br /> <div class="content"> <div> <div class="caption">Features</div> <div>Concierge</div> <div>Restaurant</div> <div>Valet Parking</div> <div>Fitness Center</div> <div>Sauna</div> <div>Airport Shuttle</div> </div> <div> <div class="caption">Rooms</div> <div>Climate control</div> <div>Air conditioning</div> <div>Coffee/tea maker</div> <div>Iron/ironing</div> </div> </div> </dx-scroll-view> </div> <dxi-toolbar-item widget="dxButton" toolbar="bottom" location="center" [options]="bookButtonOptions" > </dxi-toolbar-item> </dx-popup>
import { Component, NgModule, enableProdMode } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { DxPopupModule, DxScrollViewModule, DxTemplateModule } from 'devextreme-angular'; import { DxButtonModule, DxButtonTypes } from 'devextreme-angular/ui/button'; if (!/localhost/.test(document.location.host)) { enableProdMode(); } @Component({ selector: 'demo-app', templateUrl: 'app/app.component.html', styleUrls: ['app/app.component.css'], }) export class AppComponent { popupVisible = false; popupWithScrollViewVisible = false; bookButtonOptions: DxButtonTypes.Properties = { width: 300, text: 'Book', type: 'default', stylingMode: 'contained', onClick: () => { this.popupVisible = false; this.popupWithScrollViewVisible = false; }, }; showPopup() { this.popupVisible = true; } showPopupWithScrollView() { this.popupWithScrollViewVisible = true; } } @NgModule({ imports: [ BrowserModule, DxPopupModule, DxButtonModule, DxScrollViewModule, DxTemplateModule, ], declarations: [AppComponent], bootstrap: [AppComponent], }) export class AppModule { } platformBrowserDynamic().bootstrapModule(AppModule);
.label { font-size: 12px; } ::ng-deep .demo-container { height: 450px; display: flex; align-items: center; flex-direction: column; justify-content: center; gap: 40px; } ::ng-deep .button-container { display: flex; align-items: center; flex-direction: column; justify-content: center; gap: 15px; } ::ng-deep .dx-popup-content { font-size: 12px; } .caption { padding-bottom: 8px; font-weight: 500; } ::ng-deep .content { display: flex; justify-content: space-between; }
// 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/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.3/cjs', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.13', 'devextreme/bundles/dx.all': 'npm:devextreme@24.1.3/bundles/dx.all.js', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.8', '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', ...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.8/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.3/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.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>

A click on the second Show Popup button also displays a Popup with a scrollbar, but this scrollbar belongs to the ScrollView component. This implementation is more flexible. For example, you can enable right-to-left representation or scroll the content to a specific position. For more information about the available options, refer to the ScrollView API section.

To implement the second solution, follow the steps below:

  1. Wrap the content in the ScrollView component and place it in the Popup container.

  2. Set the height and width of the ScrollView to 100% of the popup content area.