Реализация рекурсивной структуры с использованием компонентов angular2 (без forwardRef)?

У меня есть рекурсивная структура, которая состоит из двух компонентов:

  • OptionsMenuComponent (меню)
  • MenuItemComponent (пункты меню)

OptionsMenuComponent: (Шаблон + Компонент)

Template:
    <menu-item *ngFor="let menuItem of menu.menuItems" [menuItem]="menuItem"> </menu-item>

Component:
    import { Component, Input } from '@angular/core';
    import { Menu } from '../models/menu.model';
    import { MenuItemComponent } from '../menu-item/menu-item.component';

    @Component({
        moduleId: __moduleName,
        selector: 'options-menu',
        templateUrl: 'options-menu.component.html',
        styleUrls: ['options-menu.component.css'],
        directives: [MenuItemComponent],
    })
    export class OptionsMenuComponent {
        @Input() menu: Menu;

        constructor() { }
    }

Пункт меню: (Шаблон + Компонент)

Template:
    <span class="menu-item-title">{{menuItem.title}}</span>

    <options-menu *ngIf="menuItem.subMenu != null" [menu]="menuItem.subMenu" class="sub-menu"> </options-menu>

Component:
    import { Component, Input, forwardRef } from '@angular/core';
    import { MenuItem } from '../models/menu-item.model';
    import { OptionsMenuComponent } from '../options-menu/options-menu.component';

    @Component({
        moduleId: __moduleName,
        selector: 'menu-item',
        directives: [forwardRef(() => OptionsMenuComponent)],
        templateUrl: 'menu-item.component.html',
        styleUrls: ['menu-item.component.css'],
    })
    export class MenuItemComponent {
        @Input() menuItem: MenuItem;

        constructor() { }

    }

Примечание: я удалил почти всю логику и дизайн, чтобы упростить это, поскольку это не имеет отношения

Как вы можете видеть, OptionsMenuComponent знает MenuItemComponent и наоборот.
Кроме того, вы могли заметить, что в MenuItemComponent я использовал forwardRef внутри директивы. Без этого при загрузке страницы я получаю следующую ошибку:

Ошибка: Uncaught (в обещании): неожиданное значение директивы 'undefined' в представлении компонента 'MenuItemComponent'

В настоящее время способ написания (с forwardRef) работает отлично, но TSLint недоволен и выдает следующее:

[gulp-tslint] ошибка (no-forward-ref) menu-item.component.ts[9, 18]: избегайте использования forwardRef в классе "MenuItemComponent"

Я искал в Интернете альтернативные решения и пришел с пустыми руками. Все, что я мог найти, это два предложения:

  • Мое решение с forwardRef
  • "У вас есть циклическая ссылка, вы делаете что-то не так, чтобы отделить их" (не точные слова)

Первое предложение работает, но мой вопрос, возможно ли избежать этого, потому что это не похоже на хорошую практику (и везде люди говорят, чтобы этого избежать)

Второе предложение является правильным и легко реализуемым для большинства случаев, но как мне это сделать в рекурсивной структуре (используя компоненты angular2)?

Спасибо вперед,

ps - до этого у меня были все функциональные возможности в одном компоненте, и у меня не было никаких проблем с этим единственным компонентом, ссылающимся на себя (нет необходимости в forwardRef), поэтому, пожалуйста, не рекомендую делать это, потому что это не так (пытаясь сохранить компоненты маленькие и простые)

TL; DR:
Два компонента, ссылающиеся друг на друга (требовалась рекурсивная структура). Без использования forwardRef я получаю сообщение об ошибке. Есть ли альтернативное решение, не предусматривающее использование forwardRef?

1 ответ

Вот пример рекурсивной навигации, которую я написал, с урезанным списком. короче говоря, вы определяете шаблон для рекурсии, а затем перебираете корневые дочерние элементы (набор страниц) context:{ $implicit: root.children }и для каждого дочернего элемента, перебирая корневые дочерние элементы, изменяя контекст context:{ $implicit: page.children },

<ng-template #nav let-pages>
  <ol>
    <ng-container *ngFor="let page of pages">
      <ng-container *ngIf="page.public && page.visible">
        <li>
          <a routerLink="/{{page.urlname}}">{{page.name}}</a>
          <ng-container *ngTemplateOutlet="nav; context:{ $implicit: page.children }"></ng-container>
        </li>
      </ng-container>
    </ng-container>
  </ol>
</ng-template>
<ng-container *ngTemplateOutlet="nav; context:{ $implicit: root.children }"></ng-container>
Другие вопросы по тегам