Hierarchical Drawer

The Drawer component works with a flat structure of items by design. However many real world scenarios require a navigation with hierarchical structure.

The following example demonstrates how to achieve this by adding or removing items to/from the Drawer collection depending on the currently selected item.

import { Component } from '@angular/core';
import { DrawerSelectEvent } from '@progress/kendo-angular-layout';
import { angularItems } from './items-angular';
import { reactItems } from './items-react';
import { vueItems } from './items-vue';
import { DrawerItemsCollection } from './items-collection.interface';

@Component({
  selector: 'hierarchical-drawer',
  template: `
  <div class="custom-toolbar">
  <button
    style="margin-bottom: 10px;"
    kendoButton
    icon="menu"
    look="flat"
    (click)="drawer.toggle()"
  ></button>
  <span style="margin-left: 8px; font-weight: bold; font-size: 20px;">
    Kendo UI for {{ framework }} Documentation
  </span>
</div>
<kendo-drawer-container>
  <kendo-drawer
    #drawer
    [items]="items"
    [mode]="'push'"
    [expanded]="true"
    [autoCollapse]="false"
    (select)="onSelect($event)"
  >
    <ng-template kendoDrawerHeaderTemplate>
      <div class="framework-container">
        <a (click)="changeFramework('Angular')" class="img-container">
          <img
            src="https://angular.io/assets/images/logos/angularjs/AngularJS-Shield.svg"
            class="header-img"
          />
          <p class="active">
            <span
              *ngIf="framework === 'Angular'"
              class="k-icon k-i-circle"
              style="color:rgb(175,43,45)"
            ></span>
          </p>
        </a>
        <a (click)="changeFramework('React')" class="img-container">
          <img
            src="https://cdn.worldvectorlogo.com/logos/react.svg"
            class="header-img"
          />
          <p class="active">
            <span
              *ngIf="framework === 'React'"
              class="k-icon k-i-circle"
              style="color:rgb(83,193,222)"
            ></span>
          </p>
        </a>
        <a (click)="changeFramework('Vue')" class="img-container">
          <img src="https://vuejs.org/images/logo.png" class="header-img" />
          <p class="active">
            <span
              *ngIf="framework === 'Vue'"
              class="k-icon k-i-circle"
              style="color:rgb(36,184,131)"
            ></span>
          </p>
        </a>
      </div>
    </ng-template>

    <ng-template kendoDrawerItemTemplate let-item>
      <div class="k-level-{{ item.level }}">
        <span class="k-icon {{ item.icon }}"></span>
      </div>
      {{ item.text }}

      <span
        *ngIf="item.expanded && item.children"
        class="k-icon k-i-arrow-chevron-down"
        style="position:absolute; right:0; line-height: inherit"
      ></span>

      <span
        *ngIf="!item.expanded && item.children"
        class="k-icon k-i-arrow-chevron-right"
        style="position:absolute; right:0; line-height: inherit"
      ></span>
    </ng-template>
  </kendo-drawer>
  <kendo-drawer-content>
    <shared-content [selectedItem]="selected"></shared-content>
    <angular-content [selectedItem]="selected"></angular-content>
    <react-content [selectedItem]="selected"></react-content>
    <vue-content [selectedItem]="selected"></vue-content>
  </kendo-drawer-content>
</kendo-drawer-container>
`
})
export class HierarchicalDrawerComponent {
  public selected;
  public framework = 'Angular';
  public items = angularItems.parents;
  public itemIndex;

  public gettingStarted = [
    {
      text: 'About Kendo UI',
      icon: 'k-i-question',
      selected: false,
      level: 1
    },
    {
      text: 'Supported Themes',
      icon: 'k-i-palette',
      selected: false,
      level: 1
    }
  ];
  public overviewChildren;

  public changeFramework(framework) {
    this.framework = framework;
    this.selected = '';
    switch (this.framework) {
      case 'Angular':
        this.items = angularItems.parents;
        break;
      case 'React':
        this.items = reactItems.parents;
        break;
      case 'Vue':
        this.items = vueItems.parents;
        break;
    }
    this.items.map((item) => item.selected = false);
  }


  public onSelect(ev: DrawerSelectEvent): void {
    this.selected = ev.item.text;
    const item = this.items.find((e, index) => {
      this.itemIndex = index;
      return e.text === ev.item.text;
    });

    item.expanded ? (item.expanded = false) : (item.expanded = true);

    if (ev.item.text === 'Getting Started') {
      item.expanded
        ? this.addChildren(this.gettingStarted)
        : this.removeChildren(this.gettingStarted);
    }
    if (ev.item.text === 'Overview') {
      let childItems: DrawerItemsCollection = {
        parents: [],
        children: []
      };

      switch (this.framework) {
        case 'Angular':
          childItems = angularItems;
          break;

        case 'React':
          childItems = reactItems;
          break;

        case 'Vue':
          childItems = vueItems;
      }

      item.expanded
        ? this.addChildren(childItems.children)
        : this.removeChildren(childItems.children);
    }
  }

  public addChildren(children) {
    this.items.splice(this.itemIndex + 1, 0, ...children);
  }

  public removeChildren(children: Array<any>) {
    this.items.splice(this.itemIndex + 1, children.length);
  }
}
import { Component, Input } from '@angular/core';

@Component({
  selector: 'angular-content',
  template: `
    <div id="About Angular" *ngIf="selectedItem === 'About Angular'">
      <h4 class="header">
        One framework. Mobile & desktop.
      </h4>
      <h6>
        Angular (commonly referred to as "Angular 2+" or "Angular v2 and above")
        is a <strong>TypeScript-based</strong> open-source web application
        framework led by the Angular Team at Google and by a community of
        individuals and corporations.
      </h6>
      <h6>
        Angular is a complete rewrite from the same team that built AngularJS.It
        is an open-source software engineering framework used for building
        single-page web apps. Developers also use it to create animated menus
        for HTML web pages.
      </h6>
    </div>

    <div
      id="All Angular Components"
      *ngIf="selectedItem === 'All Angular Components'"
    >
      <h4 class="header">
        <div class="example" [ngStyle]="{ 'background-color': kendokaColor }">
          <div class="kendoka"></div>
        </div>
        Check all available components of Kendo UI for Angular at the following
        <a href="https://www.telerik.com/kendo-angular-ui/components/"
          >Docs & Demos</a
        >
        article.
      </h4>
    </div>
  `
})
export class AngularContentComponent {
  @Input() selectedItem: string;
  public kendokaColor = '#fe413b';
}
import { Component, Input } from '@angular/core';

@Component({
  selector: 'react-content',
  template: `
    <div id="About React" *ngIf="selectedItem === 'About React'">
      <h4 class="header">
        React is a declarative, efficient, and flexible JavaScript library for
        building user interfaces
      </h4>
      <h6>
        React (also known as React.js or ReactJS) is a
        <strong>JavaScript</strong> library for building user interfaces. It is
        maintained by Facebook and a community of individual developers and
        companies.
      </h6>
      <h6>
        React can be used as a base in the development of single-page or mobile
        applications, as it is optimal for fetching rapidly changing data that
        needs to be recorded.
      </h6>
    </div>

    <div
      id="All React Components"
      *ngIf="selectedItem === 'All React Components'"
    >
      <h4 class="header">
        <div class="example" [ngStyle]="{ 'background-color': kendokaColor }">
          <div class="kendoka"></div>
        </div>
        Check all available components of Kendo UI for React at the following
        <a href="https://www.telerik.com/kendo-react-ui/components/"
          >Docs & Demos</a
        >
        article.
      </h4>
    </div>
  `
})
export class ReactContentComponent {
  @Input() selectedItem: string;
  private kendokaColor = '#4eaec5';
}
import { Component, Input, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'vue-content',
  template: `
    <div id="About Vue" *ngIf="selectedItem === 'About Vue'">
      <h4 class="header">
        A progressive framework for building user interfaces.
      </h4>
      <h6>
        Vue.js is an open-source <strong>JavaScript</strong> framework for
        building user interfaces and single-page applications. It was created by
        Evan You, and is maintained by him and the rest of the active core team
        members coming from various companies such as Netlify and Netguru.
      </h6>

      <h6>
        Unlike other monolithic frameworks, Vue is designed from the ground up
        to be incrementally adoptable. The core library is focused on the view
        layer only, and is easy to pick up and integrate with other libraries or
        existing projects.
      </h6>
    </div>

    <div id="All Vue Components" *ngIf="selectedItem === 'All Vue Components'">
      <h4 class="header">
        <div class="example" [ngStyle]="{ 'background-color': kendokaColor }">
          <div class="kendoka"></div>
        </div>
        Check all available components of Kendo UI for Vue at the following
        <a href="https://www.telerik.com/kendo-vue-ui/components/"
          >Docs & Demos</a
        >
        article.
      </h4>
    </div>
  `,
  encapsulation: ViewEncapsulation.None,
  styles: ['content-styles.css'],
})
export class VueContentComponent {
  @Input() selectedItem: string;
  private kendokaColor = '#42b683';
}
import { Component, Input } from '@angular/core';

@Component({
  selector: 'shared-content',
  template: `
    <div
      *ngIf="
        selectedItem === 'Angular' ||
        selectedItem === 'React' ||
        selectedItem === 'Vue'
      "
      class="header"
    >
      <h6>
        Kendo UI for {{ selectedItem }} component library allows to quickly
        build stunning and high-performance responsive web applications.
      </h6>
    </div>

    <div id="Getting Started" *ngIf="selectedItem === 'Getting Started'">
      <h4 class="header">
        A Complete UI Toolkit for Web Development
      </h4>
      <h6>
        Users demand rich, responsive, adaptive experiences on any browser or
        device. You need to deliver those compelling experiences quickly—without
        expensive custom development or design resources.
      </h6>
      <br />
      <h6>
        <strong>Progress® Kendo UI®</strong> delivers everything you need to
        build a modern web application under tight deadlines, with
        out-of-the-box features and functions that can speed your development
        time by 50 percent:
      </h6>
      <ul>
        <li>
          Flexible - Use your preferred framework, including jQuery,
          AngularJS/Angular, React, and Vue.js.
        </li>
        <li>
          Versatile - Leverage more than 200 customizable UI components spread
          across the various libraries to create eye-catching, data-rich
          desktop, tablet, and mobile web apps.
        </li>
        <li>
          Powerful - Accelerate development time with responsive layout,
          powerful data-binding, cross-browser compatibility and ready-to-use
          themes.
        </li>
        <li>
          Supported -Get started fast with easy integration backed by
          comprehensive documentation, flexible support options, hands-on
          training courses and a large developer community.
        </li>
      </ul>
    </div>

    <div id="About Kendo UI" *ngIf="selectedItem === 'About Kendo UI'">
      <h4 class="header">
        Build Better JavaScript Apps Faster
      </h4>
      <h6>
        The ultimate collection of JavaScript UI components with libraries for
        jQuery, Angular, React, and Vue. Quickly build eye-catching,
        high-performance, responsive web applications, regardless of your
        JavaScript framework choice.
      </h6>
      <ul>
        <li>Decreases time-to-market</li>
        <li>Provides advanced UI features</li>
        <li>Supports popular frameworks</li>
        <li>Reduces design risk</li>
      </ul>
      <a href="https://www.telerik.com/kendo-ui"
        >Click here for more information</a
      >
    </div>

    <div id="Supported Themes" *ngIf="selectedItem === 'Supported Themes'">
      <h4 class="header">
        Kendo UI provides themes that you can use to style your application.
      </h4>
      <h6>
        Currently, the Kendo for Angular, React and Vue ships the following
        themes:
      </h6>
      <ul>
        <li>Kendo UI Default theme</li>
        <li>Kendo UI Bootstrap theme</li>
        <li>Kendo UI Material theme</li>
      </ul>
      <h6>
        The Kendo UI <strong>Theme Builder</strong> is a web application which
        enables you to create new or customize existing themes.
      </h6>
      <h6>
        The Theme Builder renders the same look and feel as all other components
        in the suite and delivers full control over their visual elements.
      </h6>
      <a href="https://themebuilder.telerik.com">Play with the Theme Builder</a>
    </div>

    <div id="Overview" *ngIf="selectedItem === 'Overview'">
      <h4 class="header">
        Spend your time developing core functionality, not UI components
      </h4>
      <h6>
        Build your next application, or augment an existing one, with
        easy-to-use Kendo UI components designed with performance and rich user
        experience in mind.
      </h6>
      <h6>
        Easily add advanced UI components into your existing designs or take
        advantage of our comprehensive library in new design starts. Kendo UI
        lets you save time by integrating components to handle all the key
        functionality you need in a UI, letting you focus your development
        efforts on your proprietary features.
      </h6>
    </div>

    <div
      id="Most Popular Widgets"
      *ngIf="selectedItem === 'Most Popular Widgets'"
    >
      <h4 class="header">
        Most Popular Widgets
      </h4>
      <ul>
        <li>Grid</li>
        <li>Charts</li>
        <li>Dropdowns</li>
        <li>Inputs</li>
        <li>Themes</li>
      </ul>
    </div>
`
  })
export class SharedContentComponent {
  @Input() selectedItem: string;
}
import { DrawerItemsCollection } from './items-collection.interface';

export const angularItems: DrawerItemsCollection = {
    parents: [
        {
            text: 'Getting Started',
            icon: 'k-i-information',
            expanded: false,
            children: true,
            selected: false
        },
        {
            text: 'Overview',
            icon: 'k-i-zoom',
            expanded: false,
            children: true,
            selected: false
        },
        {
            text: 'Most Popular Widgets',
            icon: 'k-i-star',
            expanded: false,
            children: false,
            selected: false
        }
    ],

    children: [
        {
            text: 'About Angular',
            icon: 'k-i-connector',
            children: false,
            selected: false,
            level: 1
        },
        {
            text: 'All Angular Components',
            icon: 'k-i-style-builder',
            children: false,
            selected: false,
            level: 1
        }
    ]
};
import { DrawerItemsCollection } from './items-collection.interface';

export const reactItems: DrawerItemsCollection = {
    parents: [
        {
            text: 'Getting Started',
            icon: 'k-i-information',
            expanded: false,
            children: true,
            selected: false
        },
        {
            text: 'Overview',
            icon: 'k-i-zoom',
            expanded: false,
            children: true,
            selected: false
        },
        {
            text: 'Most Popular Widgets',
            icon: 'k-i-star',
            expanded: false,
            children: false,
            selected: false
        }
    ],

    children: [
        {
            text: 'About React',
            icon: 'k-i-connector',
            children: false,
            selected: false,
            level: 1
        },
        {
            text: 'All React Components',
            icon: 'k-i-style-builder',
            children: false,
            selected: false,
            level: 1
        }
    ]
};
import { DrawerItemsCollection } from './items-collection.interface';

export const vueItems: DrawerItemsCollection = {
    parents: [
        {
            text: 'Getting Started',
            icon: 'k-i-information',
            expanded: false,
            children: true,
            selected: false
        },
        {
            text: 'Overview',
            icon: 'k-i-zoom',
            expanded: false,
            children: true,
            selected: false
        },
        {
            text: 'Most Popular Widgets',
            icon: 'k-i-star',
            expanded: false,
            children: false,
            selected: false
        }
    ],

    children: [
        {
            text: 'About Vue',
            icon: 'k-i-connector',
            children: false,
            selected: false,
            level: 1
        },
        {
            text: 'All Vue Components',
            icon: 'k-i-style-builder',
            children: false,
            selected: false,
            level: 1
        }
    ]
};
export interface DrawerItemsCollection {
    parents?: any[];
    children?: any[];
}
import { Component, ViewEncapsulation } from '@angular/core';

@Component({
    selector: 'my-app',
    template: `
      <hierarchical-drawer></hierarchical-drawer>
    `,
    encapsulation: ViewEncapsulation.None,
    styles: [
        `
        my-app {
          padding: 0;
          font-family: "Roboto", sans-serif;
        }
        kendo-drawer-container {
          position: fixed;
          width: 100%;
          height: 100%;
        }
        .k-drawer-content {
          padding: 15px;
        }
        .k-drawer-wrapper {
          width: 243px !important;
        }
        .k-i-menu {
          font-size: 25px;
        }
        .header-img {
          cursor: pointer;
          height: 50px;
        }
        .header-img:hover {
          transform: scale(1.15);
        }
        .custom-toolbar {
          width: 100%;
          background-color: #f6f6f6;
          border-bottom: inset;
          border-bottom-width: 1px;
          padding: 3px 8px;
          color: #656565;
          line-height: 50px;
        }
        .k-level-1 {
          padding-left: 20px;
        }
        .framework-container {
          text-align: center;
          padding-top: 14px;
          display: flex;
          justify-content: space-evenly;
        }
        .img-container {
          position: relative;
          margin-bottom: 27px;
        }
        .active {
          position: absolute;
          left: 50%;
          margin-left: -8px;
        }
        .example {
          width: 300px;
          height: 300px;
          margin: 0 auto;
        }
        .kendoka {
          margin: 0 auto;
          width: 300px;
          height: 300px;
          background-size: cover;
          background-image: url("https://www.telerik.com/kendo-angular-ui-develop/components/inputs/colorpicker/assets/kendoka.png");
        }
        .header {
          text-align: center;
          margin-bottom: 30px;
        }
      `
    ]
})
export class AppComponent { }
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LayoutModule } from '@progress/kendo-angular-layout';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { AppComponent } from './app.component';
import { SharedContentComponent } from './content-shared.component';
import { AngularContentComponent } from './content-angular.component';
import { ReactContentComponent } from './content-react.component';
import { VueContentComponent } from './content-vue.component';
import { HierarchicalDrawerComponent } from './hierarchical-drawer.component';

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        LayoutModule,
        ButtonsModule
    ],
    declarations: [
        AppComponent,
        SharedContentComponent,
        AngularContentComponent,
        ReactContentComponent,
        VueContentComponent,
        HierarchicalDrawerComponent
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

In this article