paint-brush
Angular @Input を使用して動的に作成されたコンポーネントにデータを渡す方法@briantreese
379 測定値
379 測定値

Angular @Input を使用して動的に作成されたコンポーネントにデータを渡す方法

Brian Treese4m2024/02/27
Read on Terminal Reader

長すぎる; 読むには

Angular 16 では、動的に作成されたコンポーネント間で親から子にデータを渡すことができます。以前は、親で情報を提供してから、それを子コンポーネント内に挿入する必要がありました。現在は、代わりに `@Input` デコレータを使用してこれを行うことができます。
featured image - Angular @Input を使用して動的に作成されたコンポーネントにデータを渡す方法
Brian Treese HackerNoon profile picture

Angular で動的に作成されたコンポーネントを使用している場合、必要なときに親コンポーネントと子コンポーネントの間で情報を渡すのが難しいことに気付いたことがあるでしょう。親で情報を提供し、それを子コンポーネント内に挿入する必要があります。これは必ずしも難しいことではありませんが、多くの余分な定型コードが必要になります。


これまでと同じように@Inputデコレータを使用できれば、さらに良いでしょう。さて、どうでしょうか? Angular はバージョン 16 の時点でこれとまったく同じことをサポートしています。この投稿ではその方法を説明します。さて、それでは始めましょう。

Angular Injector を使用した古い方法でデータを渡す

まず、動的に作成されたコンポーネントに親からデータを渡す方法を見てみましょう。この例では、コンポーネント テンプレート内に*ngComponentOutletがあり、それをプレーヤー コンポーネントに渡しています。


この場合、カスタムの子インジェクターも渡しており、以前はこのようにして子コンポーネントにデータを注入していました。

main.ts

 @Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; injector: childInjector"></ng-container> ` }) export class App { protected playerComponent = PlayerComponent; }


この子インジェクターを作成するには、テンプレート内で設定して使用できるようにプロパティを作成する必要がありました。


 export class App { protected childInjector?: Injector; ... }


次に、コンストラクター内の angular コアからインジェクターに注入する必要がありました。


 export class App { ... constructor(private injector: Injector) { } }


その後、create メソッドとプロバイダーの配列を使用して子インジェクターを設定し、プレーヤー トークンを子に提供する必要がありました。


 export class App { ... constructor(private injector: Injector) { this.childInjector = Injector.create({ providers: [ { provide: PlayerToken, useValue: this.player } ], parent: this.injector }); } }


最後に、子コンポーネントであるプレーヤー コンポーネントで、Angular コアからの inject メソッドを使用してプレーヤー プロパティを設定する必要がありました。

player.component.ts

 export class PlayerComponent { protected player?: Player = inject(PlayerToken); }


したがって、これはすべて、単純なプレーヤー オブジェクトを動的コンポーネントに渡すだけです。つまり、これが動的コンポーネントでない場合は、これを@Inputにして、プレーヤー データ オブジェクトを親の@Inputにバインドするだけです。しかし、これは動的に作成されたコンポーネントなので、これを行うことはできませんよね?


さて、Angular 16 の時点では、実際には代わりに@Inputを使用でき、これまで見てきたものよりもはるかに単純です。

*ngComponentOutlet入力オブジェクトを使用した新しい方法でデータを渡す

まず、このプレーヤー プロパティを@Inputに変更します。そして、それはプレーヤー インターフェイスに入力されるだけです。

player.component.ts

 export class PlayerComponent { @Input() player?: Player; }


ここで、inject メソッドとプレーヤー トークンのインポートは不要になったので、削除できます。次に、親のテンプレートに戻り、インジェクターを削除し、代わりに入力オブジェクトに置き換えます。このオブジェクトを任意の数の入力に渡すことができます。したがって、入力が 5 つある場合は、それらの名前を含めるだけで、必要なデータをそれぞれに渡すことになります。


ただし、この場合、子コンポーネント player には入力が 1 つしかないため、それを渡す必要があるのはそれだけです。

main.ts

 @Component({ selector: 'app-root', template: ` <ng-container *ngComponentOutlet="playerComponent; inputs: { player }"></ng-container> ` })


これで、子インジェクターを削除できます。これは、コンストラクターを完全に削除することもできることを意味します。最後に、Angular コアとプレーヤー トークンのインポートからインジェクターを削除できます。これらは使用されなくなったためです。


 export class App { protected player: Player = { name: 'LeBron James', games: 1421, points: 38652, fieldGoalPercentage: 0.505, threePointPercentage: 0.345, imageName: 'lebron-james' }; protected playerComponent = PlayerComponent; }


以上です。すべてが以前と同じように機能していることがわかります。したがって、実行がかなり簡単になり、コードも少なくなり、常に素晴らしいことになります。


ただし、残念な点は、 @Inputはサポートされているものの、 @Outputはサポートされていないことです。ちょっと残念ですが、それが現実です。これも非常に便利なので、将来的にサポートが追加されることを願っていますが、私たちは待つしかありません。

実際の動作を見てみたいですか?

以下の Stackblitz の例で、デモ コードとこれらのテクニックの例を確認してください。ご質問やご意見がございましたら、お気軽にコメントを残してください。