Back to Blog Home
← all posts

Creating an App with Multiple Side Drawers

November 15, 2017 — by Connor Sleight

After seeing a few people mention that they needed the ability to have multiple side drawers on a single page in their apps, or to leverage side drawers with child routing, I decided to experiment with a solution to this issue by using custom components. Let's get started!

Note: Some knowledge of how custom components work in Angular is a helpful prerequisite for this tutorial.
If you make two new components following the code below for left and right menus, we will use these to keep the side drawer html page cleaner.

Step 1: Create a component

import { Component } from "@angular/core";
    selector: "left-drawer",
    template: `<StackLayout style="background-color: blue">
    <Label text="Left drawer"></Label>
    <Label text="Left Item 1"></Label>
    <Label text="Left Item 2"></Label>
export class LeftDrawerComponent { }

Doing this allows easier modification to either menu and doesn’t leave your main page’s html cluttered or overly verbose.

Step 2: Create the side drawer’s layout

Modify the html where you layout the side drawer:

<RadSideDrawer [drawerLocation]="drawerLocation" gesturesEnabled="false" tkExampleTitle tkToggleNavButton>
    <StackLayout tkDrawerContent>
        <left-drawer *ngIf="drawerLocation == 'Left'"></left-drawer>
        <right-drawer *ngIf="drawerLocation == 'Right'"></right-drawer>
        <Label text="Close Drawer" color="lightgray" padding="10" style="horizontal-align: center" (tap)="closeDrawer()"></Label>
    <StackLayout tkMainContent>
        <Button text="Left" (tap)="openDrawer('Left')"></Button>
        <Button text="Right" (tap)="openDrawer('Right')"></Button>
        <!—Your code here -->
Note: The 2 buttons in the <StackLayout tkMainContent> are there just for demonstration purposes and can be removed.
Step 3: Build the side drawer components

Then, within the TypeScript file for the component containing the side drawer, you will need to add a few extra lines of code to make sure the menus swap correctly. Start by add the following imports at the top of the file.

import { Component, ViewChild, AfterViewInit } from "@angular/core";
import { RadSideDrawerComponent } from "nativescript-pro-ui/sidedrawer/angular";
import { RadSideDrawer } from 'nativescript-pro-ui/sidedrawer'; 

Then add the following variables to your class:

@ViewChild(RadSideDrawerComponent) public drawerComponent: RadSideDrawerComponent;
private drawer: RadSideDrawer;
drawerLocation: string = "Left";

For ease, add this snippet to make writing any side drawer code quicker.

ngAfterViewInit() {
    this.drawer = this.drawerComponent.sideDrawer;

Step 4: Build the drawers’ functions

Finally, adding two basic functions will handle which menu to use, where it will be on screen and also closing the side drawer.

openDrawer(position) {
    this.drawerLocation = position;
    setTimeout(() => this.drawer.showDrawer(), 5);
closeDrawer() {
Note: This code: setTimeout(() => this.drawer.showDrawer(), 5); stops the drawer from glitching or stuttering. Sometimes this happens as it takes a few milliseconds to place the drawer where it belongs. The drawerLocation changes just before opening it so a 5 millisecond delay is unnoticeable to users but is long enough to make the drawer behave correctly.
I also tried using routing as another possible solution but routing seems to change the whole page and not just the side drawer menu. I was unable to find a way to get it to work.

It Is also possible to use swipe gestures to open the side drawer with little modification. Add:


<StackLayout tkMainContent>
to get

<StackLayout (swipe)="onSwipe($event)" tkMainContent>
You then need to add:

import { SwipeGestureEventData } from "tns-core-modules/ui/gestures";
to your imports and one simple function to the class.

onSwipe(args: SwipeGestureEventData) {
    if (args.direction == 1) {
    } else if (args.direction == 2) {

That’s all you need to make an app with multiple side drawers per page. The simplicity of the solution surprised me as I expected to have to approach the issue with a more “hacky” solution rather than a more “basic” solution. You can find a repo of the code used in this demo here.