Search code examples
angularbootstrap-4navbarngfor

Issues with Bootstrap navbar-nav when using ngFor


Hi I am using bootstrap v4.0.0. When displaying menus using navbar-nav and using ngFor, the bound property is called all the time - is this expected behavior?

HTML code snippet:

<div class="collapse navbar-collapse" id="navbar-content">
    <div class="navbar-nav mr-auto">
      <ul class="navbar-nav">
        <ng-container *ngFor="let navItem of NavItems">          
          <li class="nav-item">
            <a class="nav-link" [routerLink]="[navItem.url]" routerLinkActive="active" [target]="navItem.isLink ? '_blank' : null">{{navItem.displayName}}</a>
          </li>
        </ng-container>
    </ul>
  </div>
</div>

component.ts code snippet:

private _navItems: object;
get NavItems() { // This API is called continuously even after the menu items are loaded
   if(!this._navItems){
    this._navItems=  [
      {
        "displayName": "TestApp",
        "url": "testApp",
        "isLink": false,
        "requiredRoles": [],
        "childNavs": []
      },
      {
        "displayName": "Custom Control",
        "url": "custom",
        "isLink": false,
        "requiredRoles": [],
        "childNavs": [
          {
            "displayName": "JQX Custom Grid",
            "url": "custom/grid",
            "isLink": true,
            "requiredRoles": []
          }
        ]
      }
    ];
   }
   return this._navItems;
  }

get NavItems binding is called all the time even when nothing has changed.

  • Is this expected behavior?
  • Is there a better approach?

Thanks,

RDV


Solution

  • To elaborate on what @penleychan said, yes it is expected behaviour. Any value bound to a method in the template will call that method every change-detection cycle to ensure the value has not changed.

    As far as I can tell, your getter method is essentially static, so you could just do:

    private _navItems = 
    [
          {
            "displayName": "TestApp",
            "url": "testApp",
            "isLink": false,
            "requiredRoles": [],
            "childNavs": []
          },
          {
            "displayName": "Custom Control",
            "url": "custom",
            "isLink": false,
            "requiredRoles": [],
            "childNavs": [
              {
                "displayName": "JQX Custom Grid",
                "url": "custom/grid",
                "isLink": true,
                "requiredRoles": []
              }
            ]
          }
    ];
    
    public NavItems: object;
    
    constructor() {
      this.NavItems = this._navItems;
    }
    

    If you are updating the value of _navItems, I suggest you just update NavItems afterwards and Angular will pick up that change.