8

Ich habe eine rekursive Struktur, die aus zwei Komponenten zusammengesetzt ist:Implementierung einer rekursiven Struktur mit angular2-Komponenten (ohne forwardRef)?

  • OptionsMenuComponent (A-Menü)
  • MenuItemComponent (Die Menüpunkte)

OptionsMenuComponent: (Template + Component)

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() { } 
    } 

Menüoption: (Template + Component)

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() { } 

    } 

Hinweis: Ich entfernte fast alle Logik und Design zu vereinfachen, da es nicht relevant ist

Wie Sie die OptionsMenuComponent die MenuItemComponent weiß sehen kann und umgekehrt.
Außerdem haben Sie vielleicht bemerkt, dass ich in MenuItemComponent forwardRef innerhalb der Direktive verwendet habe. Ohne dass, wenn lade ich die Seite, die ich die folgende Fehlermeldung erhalten:

Error: Uncaught (in promise): Unexpected directive value 'undefined' on the View of component 'MenuItemComponent'

Zeit so, wie es geschrieben ist (mit forwardRef) es funktioniert super, aber TSLint ist unzufrieden mit ihm und gibt die folgenden:

[gulp-tslint] error (no-forward-ref) menu-item.component.ts[9, 18]: Avoid using forwardRef in class "MenuItemComponent"

Ich suchte im Internet nach alternativen Lösungen und kam mit leeren Händen. Alles, was ich finden konnte, ist zwei Vorschläge:

  • Meine Lösung mit den forwardRef
  • (nicht genauen Worten)

„Sie haben eine zyklische Referenz, sind Sie ihnen etwas nicht stimmt so entkoppeln tun“ Der erste Vorschlag funktioniert, aber meine Frage ist, wenn es möglich ist, dies zu vermeiden, weil es nicht wie gute Praxis klingt (Und überall Leute sagen, um es zu vermeiden)

Der zweite Vorschlag ist richtig und einfach zu implementieren für die meisten Fälle, aber wie tue ich das in einer rekursiven st (mit angular2 Komponenten)?

Dank voraus,

ps - vor diesem hatte ich alle Funktionen in einem Bauteil und ich hatte kein Problem mit dieser einzigen Komponente selbst referenzieren (keine Notwendigkeit für forwardRef) bitte nicht so tun dabei empfehlen, weil es hier nicht der Fall ist (versuchen, die Komponenten klein und einfach zu halten)

TL; DR:
Zwei-Komponenten gegenseitig referenzieren (rekursive Struktur erforderlich waren). Ohne Verwendung von forwardRef bekomme ich Fehler, gibt es eine alternative Lösung, die nicht mit forwardRef?

+0

Dies ist eine alte Frage, also ich denke, es ist mit ngModules gelöst? –

+0

@SanderElias Welche Probleme haben ngModule genau gelöst? –

+0

Probleme wie dieser. Es ermöglicht Ihnen, Code in einem Modul zu bündeln, so dass Sie nicht alles in jede Komponente aufnehmen müssen. –

Antwort

0

Hier ist ein Beispiel für ein rekursives NAV, das ich geschrieben habe und das auf eine geordnete Liste reduziert wurde.Kurz gesagt, Sie definieren eine Vorlage mit recurse, dann iterieren Sie über die Stamm-Kinder (Sammlung von Seiten) context:{ $implicit: root.children }, und bei jedem Kind, Iterieren über Stamm Kind Kinder durch Ändern des Kontexts 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>