webentwicklung-frage-antwort-db.com.de

Wie füge ich eine übergeordnete Komponente in eine untergeordnete Komponente ein?

Ich versuche, eine übergeordnete Komponente in eine untergeordnete Komponente zu injizieren. Ich dachte, das wäre einfach. Geben Sie einfach die übergeordnete Komponente in constructor() des Kindes ein:

constructor(private _parent:AppComponent) {}   // child component constructor

Ich erhalte folgende Fehlermeldung:

AUSNAHME: Alle Parameter für ChildComponent (?) Können nicht aufgelöst werden. Stellen Sie sicher, dass alle über einen gültigen Typ oder Anmerkungen verfügen.

Was vermisse ich?

ChildComponent:

import {Component} from 'angular2/core';
import {AppComponent} from './app.component';

@Component({
  selector: 'child',
  template: `<p>child</p>`
})
export class ChildComponent {
  constructor(private _parent:AppComponent) {}
}

AppComponent:

import {Component} from 'angular2/core';
import {ChildComponent} from './child.component';

@Component({
  selector: 'my-app',
  template: `{{title}} <child></child>
  `,
  directives: [ChildComponent]
})
export class AppComponent {
  title = "Angular 2 - inject parent";
  constructor() { console.clear(); }
}

Plunker

30
Mark Rajcok

Die Antwort finden Sie unter @ Kommentar von @ EricMartinez. Das Problem scheint ein Zirkelverweis zu sein, wenn A B und B A importiert.

Hier ist ein Plunker , der zwei Dateien anstelle der einen Datei in Erics Plunker verwendet.

Die einzige Änderung von meinem ursprünglichen Plunker ist die ChildComponent:

import {Component, Inject, forwardRef} from 'angular2/core';
....
constructor(@Inject(forwardRef(() => AppComponent)) private _parent:AppComponent)

Ich weiß nicht genau, ob dadurch der Zirkelverweis entfällt, da A und B sich immer noch gegenseitig importieren, aber es scheint zu funktionieren.

Siehe auch https://github.com/angular/angular/issues/3216 , wo Miško sagt:

Diese [nicht benutzerfreundliche Deklaration mit forwardRef ()] ist eine Einschränkung von JS und wie die Funktionsdeklarationen gehoben werden. Wann immer Sie eine zirkuläre Abhängigkeit haben, benötigen Sie forwardRef :-( Ich sehe nur ein Abwesendes.

Ich würde argumentieren, dass Sie sich nicht in einer Situation befinden sollten, in der Ihre Eltern über die Kinder Bescheid wissen müssen, und Kinder sollten über die Eltern Bescheid wissen. @Query sollte die meisten Anwendungsfälle berücksichtigen.

Es tut mir leid, aber obwohl ich damit einverstanden bin, dass dies in einigen seltenen Fällen ein Schmerz ist, sehe ich keinen Ausweg, und daher ist dieses Problem nicht umsetzbar und wird geschlossen.

Hmm ... Der Grund, warum ich die Eltern injiziert habe, war, dass ich zwei Möglichkeiten sehe, wie ein Kind mit einem Elternteil kommunizieren kann:

  1. das untergeordnete Element definiert die Ausgabeeigenschaften und gibt Ereignisse aus, die das übergeordnete Element abonniert
  2. das Kind injiziert das übergeordnete Element (z. B. Pane injiziert möglicherweise Tabs) und kann dann Methoden für das übergeordnete Element aufrufen

Und ich versuchte herauszufinden, wann ich jeden Ansatz verwenden sollte. Miško klingt wie 2. sollte selten sein.

Update: Ich habe noch etwas darüber nachgedacht ... 1. ist besser, weil es weniger Kopplung zwischen dem Kind und dem Elternteil gibt. Mit 1. muss das Kind die öffentliche API/Schnittstelle des Elternteils nicht kennen (und sollte es wahrscheinlich nicht wissen). 
In umgekehrter Richtung (z. B. verwendet das übergeordnete Element @ViewChild (@Query ist nun veraltet), um einen Verweis auf das untergeordnete Objekt zu erhalten, und ruft Methoden für das untergeordnete Element auf), ist die Kopplung in Ordnung, da das übergeordnete Element die untergeordnete Komponente verwendet, also benötigt die öffentliche API/Schnittstelle des untergeordneten Objekts kennen, dh die Eingabe- und Ausgabeeigenschaften und die öffentlichen Methoden.

41
Mark Rajcok

sie könnten @Host-Dekorator einfach so verwenden:

import {Component, Host} from 'angular2/core';
....
constructor(@Host() private app: AppComponent)
4
itay oded