DEV Community

Prayatna Bhattarai
Prayatna Bhattarai

Posted on

Create dynamic nested menu items in Angular

I was looking for ways to create a dynamic menu where we get list of menu items from the api and I came across this stackoverflow question

This explains how to use ngTemplateOutlet to call your own custom template to populate the menu item by referencing the same template again.

if you have an array of menuItems like this:

menuItems: MenuItem[] = [
 {
    label: 'Home',
    href: '/home',
 },
 {
    label: 'Articles',
    href: '/articles',
    children: [
    {
      label: 'News',
      href: '/articles/news',
    },
    {
      label: 'Entertainment',
      href: '/articles/entertain',
    },
     ],
 },
 {
    label: 'About',
    href: '/about',
 },
];

Enter fullscreen mode Exit fullscreen mode

I have used hardcoded value for menuItems but this can be populated by getting the value from the api.

So, on the HTML (view of the component) we only have to do is:

<nav>
 <ul class="navigation-list">
  <ng-template #menuItemTemplate let-items>
   <li *ngFor="let item of items">
    <a href="{{item.href}}">{{item.label}}</a>
     <ng-container *ngIf="item.children">
      <ul class="sub-menu">
      <ng-container *ngTemplateOutlet="menuItemTemplate; 
          context: { $implicit: item.children }">
        </ng-container>
      </ul>
     </ng-container>
    </li>
  </ng-template>
    ... more code will go here  
  </ul>
</nav>
Enter fullscreen mode Exit fullscreen mode

Above, we have created our custom template using <ng-template> that creates a reference menuItemTemplate. The let-items inside the ng-template tag creates a variable that will be replaced by the $implicit value that we define inside the context of ngTemplateOutlet. Now, whenever a menu item has it's children then it will create the template by passing in the item.children array.

But how do we actually use the menuItems that we created on the component? We just have to call the template again by simply replacing ... more code will go here with
<ng-container *ngTemplateOutlet="menuItemTemplate; context: { $implicit: menuItems }"></ng-container> by using the actual value of menuItems.

And that's it. You will have your nested menu items, no matter how many children the menuItems will hold.

Would love to know more ways that you could create dynamic menus! please drop in on the comments

P.S: the menu is not styled so feel free to use your imagination :p

Discussion (0)