Cyclic dependency error when Binding to properties of child component in ngFor

196 views Asked by At

I'm trying to bind to input properties on a child component inside of a ngFor loop to create a menu structure. I haven't been able to find anything in my searches to help, so I'm posting this question.

I'm storing the menu structure in code in the sidebar component as an array of MenuItemComponents -> MenuStructure

sidebar.component.ts: (Parent component)

export class SidebarComponent implements AfterViewInit {

  MenuStructure: MenuItemComponent[] = [];

  ngAfterViewInit() {
    //Define and Add Dashboard
      var dashboard = new MenuItemComponent(null);
      dashboard.title = 'Dashboard';
      dashboard.iconName = 'dashboard';

    //Define Documentation
      var documentation = new MenuItemComponent(null);
      documentation.title = 'Documentation';
      documentation.iconName = 'insert drive file';

    this.MenuStructure.push(dashboard);
    this.MenuStructure.push(documentation);
  }
}

This is the child component (aka. the building block of the menu):

menu-item.component.ts:

@Component({
  selector: 'app-menu-item',
  templateUrl: './menu-item.component.html',
  styleUrls: ['./menu-item.component.css']
})
export class MenuItemComponent implements OnInit {
  @Input() iconName: string;
  @Input() title: string;
  @Input() children: MenuItemComponent[] = [];
  @Input() routeLink: string = '';

  constructor(private parent: MenuItemComponent) { }

menu-item.component.html:

<a><i class="material-icons">{{iconName}}</i><span>{{title}}</span>
    <i class="material-icons" >&#xE313;</i> 
</a>

The above template is used in a ngFor loop in the sidebar template...

sidebar.component.html:

  <ul>
    <li *ngFor="let item of MenuStructure">
        <app-menu-item [title]='item.title' [iconName]='item.iconName'>
        </app-menu-item>
    </li>
  </ul>

However when trying to implement this, I get the following template error:

Template parse errors:
Cannot instantiate cyclic dependency! MenuItemComponent ("<ul>
        <li *ngFor="let item of MenuStructure">
            [ERROR ->]<app-menu-item [title]='item.title' [iconName]='item.iconName'>
            </app-menu-item>
      "): SidebarComponent@9:12

Can anyone shed some light on why it is complaining / a fix, and/or a better way to do this in angular 2?

1

There are 1 answers

0
MikeDub On

As pointed out by Amit, the error I was getting was generated from passing private parent: MenuItemComponent into the MenuItemComponent constructor (it's own constructor).

I falsely assumed that the dependency injector would create a different reference/instance for it and stop there, but turns out it was creating an infinite loop.

At this stage, I still haven't found a better solution on how to implement a Menu with children in angular 2 using components / sub-components, so anyone with a better solution is welcome to add an answer, but this answer addresses the error directly.