Today, we are going to create a simple Angular Material Dynamic sidenav menu that uses many Angular 11 APIs such as HttpClient, and Material Design.
We’ll build real-world features like Dynamic sidenav menu(role based menu) app using Angular Material 11.
![Angular Material 13 dynamic menu](https://decodedscript.com/wp-content/uploads/2021/12/dynamic-menu.gif)
Set up the JSON data for the Dynamic Sidenav Menu
Ideally, the data is fetched from a remote server for a particular role, but for the demo, we have placed JSON files locally in the application’s assets folder, afterward use the JSON data to create a dynamic sidenav menu using Angular Material 11 components.
{
"text": "Customer",
"icon": "people",
"routerLink": "/customer/manage"
},
{
"text": "Supplier",
"icon": "supervised_user_circle",
"routerLink": "/supplier/manage"
},
{
"text": "Suit",
"icon": "inventory_2",
"children": [{
"text": "Category",
"icon": "category",
"routerLink": "/product/category"
},
{
"text": "Sub Category",
"icon": "layers",
"routerLink": "/product/sub-category"
},
{
"text": "Product",
"icon": "all_inbox",
"routerLink": "/product/manage"
}
]
}
}
Creating Angular material 11 dynamic sidenav menu
Let’s start with the first step, where we’ll a component to create a dynamic menu and need is a function that fetches the menu data. Have a look at the SideNavbarComponent.ts file.
@Component({
selector: 'app-side-navbar',
templateUrl: './side-navbar.component.html',
styleUrls: ['./side-navbar.component.css']
})
export class SideNavbarComponent implements OnInit {
menuList: Observable<IMenu[]>;
constructor(private httpService: HttpclientService) { }
ngOnInit() {
this.menuList = this.httpService.getList<IMenu>("/assets/menu.json")
}
}
Next, we’ll create a dynamic menu HTML template to render menu elements using Angular material 11 components like mat-nav-list and mat-list-item component that compose our UI.
Have a look at the HTML template.
<mat-nav-list class="side-navnar">
<ng-container *ngFor="let menu of menuList | async; index as i;">
<ng-container [ngTemplateOutlet]="menu.children ? childMenu : parentMenu"
[ngTemplateOutletContext]="{menu:menu}">
</ng-container>
</ng-container>
</mat-nav-list>
<ng-template #parentMenu let-menu="menu">
<mat-list-item [routerLink]="menu.routerLink" routerLinkActive="is-active" [routerLinkActiveOptions]="{exact:
true}">
<mat-icon>{{menu.icon}}</mat-icon> {{menu.text}}
</mat-list-item>
</ng-template>
In the above code, we are using ngTemplateOutlet with the condition to display the parent or child menu. the below is the child or sub-menu HTML template.
<ng-template #childMenu let-menu="menu">
<mat-expansion-panel [class.mat-elevation-z0]="true">
<mat-expansion-panel-header>
<mat-icon mat-list-icon>{{menu.icon}}</mat-icon>{{menu.text}}
</mat-expansion-panel-header>
<mat-nav-list>
<mat-list-item [routerLink]="submenu.routerLink" *ngFor="let submenu of menu.children" routerLinkActive="is-active" [routerLinkActiveOptions]="{exact:
true}">
<mat-icon>{{submenu.icon}}</mat-icon> {{submenu.text}}
</mat-list-item>
</mat-nav-list>
</mat-expansion-panel>
</ng-template>
Next, open the app-sidebar.component.html file and add the following code.
<div class="sidebar-container">
<mat-toolbar color="primary" class="sidebar-toolbar">
<button mat-icon-button (click)="snav.toggle()">
<mat-icon>menu</mat-icon>
</button>
<h1 class="sidebar-app-name">Sidenav App</h1>
<app-header></app-header>
</mat-toolbar>
<mat-sidenav-container class="sidebar-sidenav-container">
<mat-sidenav #snav mode="side" fixedTopGap="56" opened="true">
<app-side-navbar></app-side-navbar>
</mat-sidenav>
<mat-sidenav-content class="router-container">
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
Let’s define the styles for this component to the template. add the styles for the app to app.scss.
::ng-deep .mat-expansion-panel-header {
padding: 0 16px !important;
}
::ng-deep .mat-nav-list .mat-icon {
margin-right: 10px;
}
::ng-deep .mat-expansion-panel-body {
padding: 0 !important
}
::ng-deep .mat-expansion-panel-header {
height: 48px !important;
}
::ng-deep .mat-expansion-panel .mat-list-item {
padding-left: 15px !important;
}
::ng-deep .mat-nav-list .is-active {
background-color: rgb(204, 204, 204)!important;
border-left : 8px solid rgb(139, 137, 133);
width : calc(100% - 8px)!important;;
}
::ng-deep .mat-list-base {
padding-top: 0 !important;
}
::ng-deep .mat-nav-list .mat-list-item.is-active .mat-list-item-content {
padding: 0 8px;
}
Finally, we have completed creating a dynamic menu app. You can customize this application with your styles and concepts.
Source code available for download
The source code is available on GitHub for the Angular material 11 image upload.
URL:https://github.com/decodedscript/angular-material-dynamic-nested-sidenav-menu