Backend API
<div class="demo-container">
<div class="content">
<div class="label">Catalog:</div>
<dx-menu
#menu
[dataSource]="products"
(onItemClick)="itemClick($event)"
(onSubmenuShowing)="onSubmenuShowing($event)"
>
</dx-menu>
</div>
<div class="options">
<div class="caption">Options</div>
<div class="option">
<dx-check-box
text="Limit submenu height to {{ SUBMENU_HEIGHT }}px"
[(value)]="limitSubmenuHeight"
></dx-check-box>
</div>
</div>
</div>
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import { DxCheckBoxModule } from 'devextreme-angular';
import { DxMenuModule, type DxMenuTypes } from 'devextreme-angular/ui/menu';
import notify from 'devextreme/ui/notify';
import { Service, type Product } from './app.service';
if (!document.location.host.includes('localhost')) {
enableProdMode();
}
@Component({
selector: 'demo-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [Service],
imports: [
DxMenuModule,
DxCheckBoxModule,
],
})
export class AppComponent {
products: Product[];
SUBMENU_HEIGHT = 200;
limitSubmenuHeight = false;
constructor(service: Service) {
this.products = service.getProducts();
}
itemClick(e: DxMenuTypes.ItemClickEvent<Product>) {
if (!e.itemData.items) {
notify(`The "${e.itemData.text}" item was clicked`, 'success', 1500);
}
}
onSubmenuShowing({ submenuContainer }: DxMenuTypes.SubmenuShowingEvent) {
submenuContainer.style.maxHeight = this.limitSubmenuHeight ? `${this.SUBMENU_HEIGHT}px` : '';
}
}
bootstrapApplication(AppComponent, {
providers: [
provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }),
],
});
::ng-deep .demo-container {
display: flex;
}
::ng-deep .label {
font-size: 22px;
padding-bottom: 24px;
}
::ng-deep .content {
flex-grow: 1;
width: 100%;
min-width: 500px;
overflow: clip;
}
::ng-deep .options {
display: flex;
flex-direction: column;
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
}
::ng-deep .caption {
font-size: 18px;
font-weight: 500;
}
::ng-deep .option {
margin-top: 10px;
}
import { Injectable } from '@angular/core';
class ProductItem {
text: string;
}
export class Product {
text: string;
items: (Product | ProductItem)[];
}
const products: Product[] = [
{
text: 'Electronics',
items: [
{
text: 'Computers',
items: [
{
text: 'Desktops',
},
{
text: 'Laptops',
},
{
text: 'Tablets',
},
{
text: 'Monitors',
},
{
text: 'Printers',
},
{
text: 'Scanners',
},
{
text: 'Servers',
},
{
text: 'Network Devices',
},
{
text: 'Warranties',
},
{
text: 'Projectors & Screens',
},
{
text: 'Computer Accessories',
},
],
},
{
text: 'Cell Phones',
items: [
{
text: 'Home & Office Phones',
},
{
text: 'Smart Phones & PDAs',
},
{
text: 'Senior Cell Phones',
},
{
text: 'Mobile Broadband Devices',
},
{
text: 'Cell Phone Accessories',
},
],
},
{
text: 'Camera & Photo',
items: [
{
text: 'Action Cameras',
},
{
text: 'Camcorders',
},
{
text: 'Digital Cameras',
},
{
text: 'Digital Picture Frames',
},
{
text: 'Film Cameras',
},
{
text: 'Professional Video Cameras',
},
{
text: 'Flashes',
},
{
text: 'Lenses',
},
{
text: 'Photo Printers',
},
{
text: 'Film & Slide Scanners',
},
{
text: 'Slide Projectors',
},
{
text: 'Slide Viewers',
},
{
text: 'Tripods & Monopods',
},
{
text: 'Underwater Video & Photography',
},
{
text: 'Camera Accessories',
},
],
},
{
text: 'Audio',
items: [
{
text: 'Boomboxes',
},
{
text: 'DVD & CD Player Bags',
},
{
text: 'Hi-Fi & Home Audio Accessories',
},
{
text: 'Media Streaming Devices',
},
{
text: 'MP3 & Digital Media Players',
},
{
text: 'MP3 Player Accessories',
},
{
text: 'Personal Cassette Players',
},
{
text: 'Personal CD Players',
},
{
text: 'Compact Stereos',
},
{
text: 'Speakers',
},
],
},
{
text: 'Home Appliances',
items: [
{
text: 'Air Conditioners',
},
{
text: 'Coffee Machines',
},
{
text: 'Fans',
},
{
text: 'Lamps',
},
{
text: 'Microwaves',
},
{
text: 'Refrigerators',
},
{
text: 'Washers & Dryers',
},
{
text: ' Water Heaters',
},
{
'text': 'Vacuum',
},
{
text: 'Steaming & Ironing',
},
],
},
],
},
{
text: 'Entertainment',
items: [
{
text: 'Films & Music',
items: [
{
text: 'TV Shows',
},
{
text: 'DVD',
},
{
text: 'Blu-ray',
},
{
text: 'CD',
},
{
text: 'SACD',
},
{
text: 'Vinyl',
},
{
text: 'Cassette',
},
{
text: 'Musical Instruments',
},
{
text: 'DJ Equipment',
},
],
},
{
text: 'Games & Toys',
items: [
{
text: 'PC Games',
},
{
text: 'Virtual Reality',
},
{
text: 'Boxed Games',
},
{
text: 'Download Games',
},
{
text: 'Handheld Game Systems',
},
{
text: 'Legacy Systems',
},
{
text: 'Cards',
},
],
},
],
},
{
text: 'Healthcare & Living',
items: [
{
text: 'Sports & Outdoors',
items: [
{
text: 'Camping',
},
{
text: 'Fitness',
},
{
text: 'Football',
},
{
text: 'Cycling',
},
{
text: 'Running',
},
{
text: 'Sport Electronics',
},
{
text: 'Sport Apparel',
},
{
text: 'Trainers & Tennis Shoes',
},
],
},
{
text: 'Beauty',
items: [
{
text: 'Bath & Shower',
},
{
text: 'Skin Care',
},
{
text: 'Hair Care',
},
{
text: 'Nail Care',
},
{
text: 'Make-up',
},
{
text: 'Fragrance',
},
{
text: 'Salon & SPA Equipment',
},
{
text: 'Tools & Accessories',
},
],
},
{
text: 'Fashion',
items: [
{
text: 'Clothing',
},
{
text: 'Jewellery',
},
{
text: 'Shoes',
},
{
text: 'Handbags & Shoulder Bags',
},
{
text: 'Watches',
},
{
text: 'Accessories',
},
],
},
],
},
];
@Injectable()
export class Service {
getProducts(): Product[] {
return products;
}
}
<!DOCTYPE html>
<html 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/26.1.5/css/dx.light.css" />
</head>
<body class="dx-viewport">
<demo-app>Loading...</demo-app>
<script src="https://cdn.jsdelivr.net/npm/zone.js@0.16.2/bundles/zone.umd.js"></script>
<script src="./bundle.js" type="module"></script>
</body>
</html>