Search code examples
angularprimengprimeng-menu

Angular 8 + PrimeNG PanelMenu - how to dynamically add menu items


Is it possible to set menu items based on data fetched from database?

import {Component, OnInit} from '@angular/core'; import {MenuItem} from 'primeng/api';

@Component({
  selector: 'app-questionnaire',
  templateUrl: './questionnaire.component.html',
  styleUrls: ['./questionnaire.component.scss'],
})
export class QuestionnaireComponent implements OnInit {
  items: MenuItem[];

  constructor() {
  }

  ngOnInit() {
    this.items = [
      {
        label: 'Environmental',
        items: [
          {
            label: 'Question 1',
            icon: 'pi pi-circle-on',
          },
          {
            label: 'Question 2',
            icon: 'pi pi-circle-on',
          },
          {
            label: 'Question 3',
            icon: 'pi pi-circle-on',
          },
        ],
      }, {
        label: 'Social',
        items: [
          {
            label: 'Question 4',
            icon: 'pi pi-circle-on',
          },
          {
            label: 'Question 5',
            icon: 'pi pi-circle-on',
          },
          {
            label: 'Question 6',
            icon: 'pi pi-circle-on',
          },
        ],
      },
      {
        label: 'Governance',
        items: [
          {
            label: 'Question 7',
            icon: 'pi pi-circle-on',
          },
          {
            label: 'Question 8',
            icon: 'pi pi-circle-on',
          },
          {
            label: 'Question 9',
            icon: 'pi pi-circle-on',
          }, {
            label: 'Question 10',
            icon: 'pi pi-circle-on',
          },
        ],
      },
    ];
  }
}

and my template:

<div class="questionnaire questionnaire-container">
  <div class="intro"></div>
  <div class="content">
    <div class="progress-bar">
      PROGRESS BAR
    </div>
    <div class="side-menu">
      <p-panelMenu [model]="items" [style]="{'width':'300px'}"></p-panelMenu>
    </div>
    <div class="questionnaire-content">
      QUESTIONNAIRE CONTENT
    </div>
  </div>
</div>

I'm asking you because I don't know if its possible to do that in component, not in template where I could use *ngFor= and then generate menu items... If it's not possible, then I would find some other library for menu...


Solution

  • Yes it is possible.
    You will just have to use Angular's http client to request the data you want, then subscribe to it and assign the resuts to this.items.
    The trickiest part is gonna be formatting you data from your API to a format that can be understood by PrimeNG menu panel. In the example below I make a call to an API that returns to me a formatted items which I can assign directly to this.items :

      ngOnInit() {
        this.http
          .get("https://express-demo-feat-test2-s8pihd.herokuapp.com/api/items")
          .subscribe(data => (this.items = data as MenuItem[]));
      }
    

    Here is a link to a stackblitz demo
    If you need to format your data before using it you can do something like this:

      ngOnInit() {
        this.http
          .get("https://express-demo-feat-test2-s8pihd.herokuapp.com/api/items")
          .pipe(
             map(data => {
               // do some formatting
             })
          )
          .subscribe(data => (this.items = data as MenuItem[]));
      }