親コンポーネントを子コンポーネントに注入しようとしています。これは簡単だと思いました-単に子の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(); }
}
答えについては、@ 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つの方法を見ているからです。
そして、私は各アプローチをいつ使用するかを決定しようとしていました。 Miškoは2のように聞こえますが、まれなはずです。
更新:私はこれについてもう少し考えていました... 1.子と親の間の結合が少ないため、より良いです。 1.では、子は親のパブリックAPI /インターフェイスを知る必要はありません(おそらく知らないはずです)。
逆方向(たとえば、親は@ViewChild
(@Query
は非推奨です)、子への参照を取得し、子のメソッドを呼び出します)、親は子コンポーネントを使用しているので、子のパブリックAPI /インターフェースを知る必要があるため、結合は良好です:つまり、入力および出力プロパティとパブリックメソッドです。
次のように@Hostデコレータを使用できます。
import {Component, Host} from 'angular2/core';
....
constructor(@Host() private app: AppComponent)