skip to Main Content

I am trying to make a collapsible menu in my header component and I am having trouble with correct JSON formating in my angular project. I keep getting this error:

Error: src/app/components/header/header.component.html:48:49 – error
TS2339: Property ‘sublinks’ does not exist on type ‘{ title: string;
collapsed: boolean; links: { title: string; url: string; sublinks: {
title: string; url: string; }[]; }[]; }’.

48 <li *ngFor="let sublink of item.sublinks"
class="sublink">

I can’t seem to resolve this error on my own and would like some help.

My HTML template is this:

<li *ngFor="let item of navigationItems; let i = index" class="link">
            <a [href]="item.url" class="main-wrapper">{{ item.title }}</a>
            <a class="d-inline-block main-wrapper" (click)="toggleCollapse(i)" role="button" [attr.aria-expanded]="!item.collapsed" [attr.aria-controls]="'navCollapse_' + i">
              <img *ngIf="item.collapsed" src="./assets/img/icons/plus.svg" alt="plus-icon" class="ms-3">
              <img *ngIf="!item.collapsed" src="./assets/img/icons/minus.svg" alt="minus-icon" class="ms-3">
            </a>
            <div [id]="'navCollapse_' + i" class="collapse link-collapse main-collapse" [class.show]="!item.collapsed">
              <ul class="sublink-wrapper">
                <li *ngFor="let sublink of item.sublinks" class="sublink">
                  <a [href]="sublink.url">{{ sublink.title }}</a>
                </li>
              </ul>
            </div>
          </li>

My TS code is this:

export class HeaderComponent {
  constructor() { }

  navigationState: string = 'out';
  
  navigationItems = [
    {
      title: 'Lorem ipsum',
      collapsed: true,
      links: [
        {
          title: 'Lorem ipsum 1',
          url: 'some-url',
          sublinks: [
            { title: 'Lorem ispum 1.1', url: 'some url' },
            { title: 'Lorem ispum 1.2', url: 'some url' },
            { title: 'Lorem ispum 1.3', url: 'some url' }
          ]
        },
        {
          title: 'Lorem ipsum 2',
          url: 'some-url',
          sublinks: [
            { title: 'Lorem ispum 2.1', url: 'some url' },
            { title: 'Lorem ispum 2.2', url: 'some url' },
            { title: 'Lorem ispum 2.3', url: 'some url' },
            { title: 'Lorem ispum 2.4', url: 'some url' }
          ]
        },
        {
          title: 'Lorem ipsum 3',
          url: 'some-url',
          sublinks: [
            { title: 'Lorem ispum 3.1', url: 'some url' },
            { title: 'Lorem ispum 3.2', url: 'some url' },
            { title: 'Lorem ispum 3.3', url: 'some url' }
          ]
        },
        {
          title: 'Lorem ipsum 4',
          url: 'some-url',
          sublinks: [
            { title: 'Lorem ispum 4.1', url: 'some url' },
            { title: 'Lorem ispum 4.2', url: 'some url' },
            { title: 'Lorem ispum 4.3', url: 'some url' },
            { title: 'Lorem ispum 4.4', url: 'some url' },
            { title: 'Lorem ispum 4.5', url: 'some url' }
          ]
        },
      ]
    }
  ];

  ngOnInit(): void {
  }

  toggleCollapse(index: number): void {
    this.navigationItems[index].collapsed = !this.navigationItems[index].collapsed;
  }

}

2

Answers


  1. Jaromanda X says correct, sublinks is a property of object in the links. So you should iterate over ‘links’ first. And totally you must have 3 *ngFor (not 2): over navigationItems, then links, then sublinks. Also you can consider removing *ngIf` and use ternar operator for src and alt. So finally I’d expect to see something like this:

    <li *ngFor="let item of navigationItems; let i = index" class="link">
          <a class="main-wrapper" (click)="toggleCollapse(i)" role="button" [attr.aria-expanded]="!item.collapsed" [attr.aria-controls]="'navCollapse_' + i">
            {{ item.title }}
            <img [src]="item.collapsed ? './assets/img/icons/plus.svg' : './assets/img/icons/minus.svg'" [alt]="item.collapsed ? 'plus-icon' : 'minus-icon'" class="ms-3">
          </a>
          <div [id]="'navCollapse_' + i" class="collapse link-collapse main-collapse" [class.show]="!item.collapsed">
            <ul class="sublink-wrapper">
              <li *ngFor="let link of item.links" class="sublink">
                <a [href]="link.url">{{ link.title }}</a>
                <ul *ngIf="!item.collapsed" class="sub-sublink-wrapper">
                  <li *ngFor="let sublink of link.sublinks" class="sub-sublink">
                    <a [href]="sublink.url">{{ sublink.title }}</a>
                  </li>
                </ul>
              </li>
            </ul>
          </div>
        </li>
    
    Login or Signup to reply.
  2. constructor() { }
    
      navigationState: string = 'out';
      
      navigationItems:any = [
        {
          title: 'Lorem ipsum',
          collapsed: true,
          links: [
            {
              title: 'Lorem ipsum 1',
              url: 'some-url',
              sublinks: [
                { title: 'Lorem ispum 1.1', url: 'some url' },
                { title: 'Lorem ispum 1.2', url: 'some url' },
                { title: 'Lorem ispum 1.3', url: 'some url' }
              ]
            },
            {
              title: 'Lorem ipsum 2',
              url: 'some-url',
              sublinks: [
                { title: 'Lorem ispum 2.1', url: 'some url' },
                { title: 'Lorem ispum 2.2', url: 'some url' },
                { title: 'Lorem ispum 2.3', url: 'some url' },
                { title: 'Lorem ispum 2.4', url: 'some url' }
              ]
            },
            {
              title: 'Lorem ipsum 3',
              url: 'some-url',
              sublinks: [
                { title: 'Lorem ispum 3.1', url: 'some url' },
                { title: 'Lorem ispum 3.2', url: 'some url' },
                { title: 'Lorem ispum 3.3', url: 'some url' }
              ]
            },
            {
              title: 'Lorem ipsum 4',
              url: 'some-url',
              sublinks: [
                { title: 'Lorem ispum 4.1', url: 'some url' },
                { title: 'Lorem ispum 4.2', url: 'some url' },
                { title: 'Lorem ispum 4.3', url: 'some url' },
                { title: 'Lorem ispum 4.4', url: 'some url' },
                { title: 'Lorem ispum 4.5', url: 'some url' }
              ]
            },
          ]
        }
      ];
    
      ngOnInit(): void {
      }
    
      toggleCollapse(index: number): void {
        this.navigationItems[index].collapsed = !this.navigationItems[index].collapsed;
      }
    
    }
    
    <li *ngFor="let item of navigationItems; let i = index" class="link">
        <a [href]="item?.url" class="main-wrapper">{{ item.title }}</a>
        <a class="d-inline-block main-wrapper" (click)="toggleCollapse(i)" role="button" [attr.aria-expanded]="!item.collapsed" [attr.aria-controls]="'navCollapse_' + i">
          <img *ngIf="item.collapsed" src="./assets/img/icons/plus.svg" alt="plus-icon" class="ms-3">
          <img *ngIf="!item.collapsed" src="./assets/img/icons/minus.svg" alt="minus-icon" class="ms-3">
        </a>
        <div [id]="'navCollapse_' + i" class="collapse link-collapse main-collapse" [class.show]="!item.collapsed">
          <ul class="sublink-wrapper">
            <li *ngFor="let sublink of item?.sublinks" class="sublink">
              <a [href]="sublink.url">{{ sublink.title }}</a>
            </li>
          </ul>
        </div>
      </li>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search