Come faccio a iniettare un componente genitore in un componente figlio?

Sto cercando di iniettare un componente principale in un componente figlio. Ho pensato che sarebbe stato semplice: basta specificare / iniettare il componente genitore nel constructor() del bambino constructor() :

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

Ottengo il seguente errore:

ECCEZIONE: imansible risolvere tutti i parametri per ChildComponent (?). Assicurati che abbiano tutti un tipo o annotazioni validi.

Cosa mi manca?

ChildComponent:

 import {Component} from 'angular2/core'; import {AppComponent} from './app.component'; @Component({ selector: 'child', template: `

child

` }) export class ChildComponent { constructor(private _parent:AppComponent) {} }

AppComponent:

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

Plunker

Vedi il commento di @ EricMartinez per la risposta. Il problema sembra essere un riferimento circolare quando A importa B e B importa A.

Ecco un plunker che usa due file invece del file che si trova nel plunker di Eric .

L’unico cambiamento dal mio plunker originale è in ChildComponent:

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

Non so per certo se questo elimina il riferimento circolare, poiché A e B si stanno ancora importando a vicenda, ma sembra funzionare.

Vedi anche https://github.com/angular/angular/issues/3216 , dove afferma Miško:

Questa [dichiarazione non user-friendly che usa forwardRef ()] è una limitazione di JS e di come le dichiarazioni di funzione vengono issate. Ogni volta che hai una dipendenza circolare hai bisogno di forwardRef 🙁 Non vedo proprio una via di mezzo.

Direi che non dovresti trovarti in una situazione in cui i tuoi genitori debbano sapere dei bambini e dei bambini che devono conoscere i genitori. @Query dovrebbe prendersi cura della maggior parte dei casi d’uso.

Mi dispiace, ma mentre sono d’accordo questo è un dolore in alcuni rari casi, non vedo una via d’uscita, e quindi questo problema non è perseguibile, si chiuderà.

Hmm … il motivo per cui ho provato a iniettare il genitore è perché vedo due modi in cui un bambino può comunicare con un genitore:

  1. il figlio definisce le proprietà di output ed emette eventi a cui l’utente principale si abbona
  2. il bambino inietta il genitore (ad esempio, Pane potrebbe iniettare le tabs) e può quindi chiamare i metodi sul genitore

E stavo cercando di determinare quando utilizzare ogni approccio. Miško fa sembrare 2. dovrebbe essere raro.

Aggiornamento: stavo pensando a questo un po ‘di più … 1. è meglio perché c’è meno accoppiamento tra il bambino e il genitore. Con 1. il bambino non ha bisogno di sapere (e probabilmente non dovrebbe sapere) l’API / interfaccia pubblica del genitore.
Nella direzione inversa (ad esempio, il genitore usa @ViewChild ( @Query ora è deprecato) per ottenere un riferimento al figlio, quindi chiama i metodi sul figlio), l’accoppiamento va bene, perché il genitore sta usando il componente figlio, quindi ha bisogno di conoscere l’API / interfaccia pubblica del bambino: cioè, le proprietà di input e output e i metodi pubblici.