web-dev-qa-db-ja.com

親コンポーネントを子コンポーネントに注入するにはどうすればよいですか?

親コンポーネントを子コンポーネントに注入しようとしています。これは簡単だと思いました-単に子のconstructor()で親コンポーネントを指定/注入します:

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

次のエラーが表示されます。

例外:ChildComponent(?)のすべてのパラメーターを解決できません。すべてのタイプまたは注釈が有効であることを確認してください。

私は何が欠けていますか?

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

36
Mark Rajcok

答えについては、@ EricMartinezの comment を参照してください。問題は、AがBをインポートし、BがAをインポートする場合の循環参照のようです。

Eric's plunker にある1つのファイルの代わりに2つのファイルを使用する plunker です。

元のプランカーからの唯一の変更は、ChildComponentにあります。

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

AとBがまだ相互にインポートしているため、循環参照が削除されるかどうかはわかりませんが、うまくいくようです。

https://github.com/angular/angular/issues/3216 も参照してください。Miškoは次のように述べています。

この[forwardRef()を使用したユーザーフレンドリーでない宣言]は、JSの制限であり、関数宣言がホイストされる方法です。循環依存関係があるときはいつでもforwardRefが必要になります:-(周りに離れているところは見当たりません。

私は、あなたの親が子供について知る必要があり、子供が親について知る必要がある状況にいてはならないと主張します。 @Queryは、ほとんどのユースケースを処理する必要があります。

申し訳ありませんが、これはいくつかのまれなケースでは苦痛であることに同意しますが、そこから抜け出す方法が見当たらないため、この問題は実行可能ではなく、終了します。

うーん...私が親を注入しようとした理由は、子供が親と通信するための2つの方法を見ているからです。

  1. 子は出力プロパティを定義し、親がサブスクライブするイベントを発行します
  2. 子は親を注入し(たとえば、ペインはTabsを注入する場合があります)、親のメソッドを呼び出すことができます

そして、私は各アプローチをいつ使用するかを決定しようとしていました。 Miškoは2のように聞こえますが、まれなはずです。

更新:私はこれについてもう少し考えていました... 1.子と親の間の結合が少ないため、より良いです。 1.では、子は親のパブリックAPI /インターフェイスを知る必要はありません(おそらく知らないはずです)。
逆方向(たとえば、親は@ViewChild@Queryは非推奨です)、子への参照を取得し、子のメソッドを呼び出します)、親は子コンポーネントを使用しているので、子のパブリックAPI /インターフェースを知る必要があるため、結合は良好です:つまり、入力および出力プロパティとパブリックメソッドです。

46
Mark Rajcok

次のように@Hostデコレータを使用できます。

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