ステップ・バイ・ステップで学ぶ
Angularアプリケーション
開発ガイド
Angular エッセンシャル入門チュートリアル
Angularは、Googleによって作成・メンテナンスされ、広く使用されているWebアプリケーションプラットフォームおよびフレームワークです。AngularJSを全面的に書き直したもので、「Angular」という名称は、バージョン2以降のすべてのバージョンのフレームワークを含む意味を持っています。
TypeScriptはAngularの中核であり、Angularが記述されている言語です。そのため、AngularはTypeScriptライブラリのような主要かつ中核的な機能を実装しながら、HTMLを追加してクライアントアプリケーションを構築します。
Angularは、多岐にわたる理由から、開発者の間で高い人気を誇っています。コンポーネントとクラスベースのシステム、モジュールの仕組み、階層構造、シンプルで宣言的なテンプレートなど、メンテナンスが容易であることに加えサーバーサイドレンダリングの速さなど、そのクロスプラットフォーム機能は、大企業や中小企業の開発者にとって有利です。
このクイックAngularエッセンシャルガイドは、Angularの重要な部分と、Webベースのアプリケーションのために成長し続けるプラットフォームで作業するための主要な概念について説明します。
AngularとAngularJSの違いについて
AngularとAngularJSの間には、知っておかなければならないいくつかの主な違いがあります。
- モジュール性 - Angularのコア機能の多くがモジュールに移行しています。
- 階層構造 - Angularはコンポーネントの階層構造を中心に構築されたアーキテクチャを持っています。
- 構文 - Angularはイベントとプロパティバインディングのために異なる式の構文を持っています。
- ダイナミックローディング - Angularはランタイムにライブラリをメモリにロードし、関数を取得・実行し、その後ライブラリをメモリからアンロードします。
- 反復的なコールバック - RxJSを使用することで、Angularは非同期またはコールバックベースのコードを簡単に構成することができます。
- 非同期テンプレートコンパイル - コントローラと「スコープ」の概念がないAngularでは、テンプレートのレンダリングを一時停止し、テンプレートをコンパイルして定義されたコードを生成することが容易にできます。
Angular Ivy
Ivy は Angular のレンダリングエンジンを書き直したものです。Ivyでは、コンポーネントを互いに独立してコンパイルすることができます。これにより、アプリケーションは変更のあったコンポーネントのみを再コンパイルするため、開発時間が短縮されます。ライブラリやアプリケーションの作者の方はhttps://docs.angular.lat/guide/ivy、新旧のAngularエンジンの互換性を実現するための詳細や推奨事項を確認してください。
Tree Shaking
Ivy は、Angular コンポーネントの管理を改善するツリーシェイクを使用するように設計されています。ビルド時に未使用のコードがバンドルに含まれないようにすることで、アプリケーションのサイズを小さくすることができます。バンドルが小さいということは、起動時間が速いということです。コードの分割はバンドルをさらに最適化します。
Locality
Angularアプリ全体をコンパイルするのではなく、変更されたものだけをコンパイルするため、各コンポーネントは独自のローカル情報で独立してコンパイルでき、リビルドが大幅に速くなります。
遅延ロード
Ivyを使えば、AngularNgModuleを必要とせず、コンポーネントを遅延ロードすることができます。また、遅延ロードされたコンポーネントが使用するパッケージは、遅延ロードされたチャンクにバンドルされます。
グローバル化
ロケールは、コンパイル時に登録する必要はありません。その代わり、実行時に動的にロードすることができ、1つのアプリケーションバンドルで複数の言語をサポートすることができます。つまり、言語を変更したい場合でも、アプリケーションを再起動する必要がないのです。
デバッグ
Ivy は Debug モードに新しい機能を提供し、スタックトレースを改善することで、エラーがどこから発生したのかについてより多くの情報をもたらします。
テストの高速化
Ivy の TestBed の新しい実装では、コンポーネントが手動でオーバーライドされない限り、テスト間の再コンパイルが回避されます。これにより、テストの速度が 40 -50% 向上します。
Angularの基本的なアーキテクチャ
ここでは、関連するアーキテクチャの概要と、本ガイドで取り上げるビルディングブロックについて説明します。
- NgModules - アプリケーションドメイン、ワークフロー、または関連する機能のセットに特化したコンポーネントのセットのためのコンパイルコンテキストを宣言します。
- コンポーネント - アプリケーションのデータとロジックを含むクラスを定義し、ビューを定義する HTML テンプレートと連動します。
- テンプレート - HTMLとAngularマークアップを組み合わせ、表示される前にHTML要素を修正することができます。
- ディレクティブ - DOM 内の要素にカスタムビヘイビアをアタッチします。
- 双方向のデータバインディング - テンプレートのパーツとコンポーネントのパーツを調整する。
- サービス - 一般的に、モジュール性と再利用性を高めるために使用されるクラスで、目的が狭く明確に定義されている。
- 依存性注入 - 必要なサービスをコンポーネントに提供し、サービスクラスへのアクセスを提供します。
- ルーティング - アプリケーション内のナビゲーションを簡単に実装することができます。
この図は、構成要素間の関係を最もよく表しています。
Angularの開発環境の構築
環境を整えるには、まずAngular CLIツールでAngularをダウンロードする必要があります。Node.jsとnpmがインストールされていないマシンの場合は、必ずこちらからダウンロードしてインストールしてください。その後、Angular CLIのグローバルインストールを実行します。
npm install --g @angular/cli
AngularのNgModule
AngularのNgModuleとは何でしょうか?基本的にAngularにおけるNgModuleは、@NgModuleデコレーターでマークされたクラスのことです。NgModuleは関連する項目を整理するのに優れており、インジェクタとコンパイラの両方を設定する機能があります。
このデコレータは、コンポーネントのテンプレートをコンパイルする方法と、実行時にインジェクタを作成する方法に関する情報を、すべてメタデータオブジェクトの中に持っています。推測されるように、@NgModule は、自身のディレクティブ、コンポーネント、パイプ、およびこれらの部分に依存する外部コンポーネント間のギャップを特定し、橋渡しをする役割を果たします。
また、exportsプロパティは、モジュールの機能の一部を公開し、外部コンポーネントがそれらを効果的に使用できるようにします。
最後に、@NgModule はアプリケーションの依存性インジェクタにサービスプロバイダを追加し、アプリケーションをより柔軟にするための基盤も提供します。
Angularディレクティブ - 種類と例
ディレクティブはDOM要素を作成し、Angularアプリケーションの中でその構造や動作を変更します。Angularには3種類のディレクティブがあります。
- コンポーネント - テンプレート付きのディレクティブ。
- 属性ディレクティブ - 要素、コンポーネント、その他のディレクティブの外観や動作を変更します。
- 構造ディレクティブ - 要素の追加や削除により、DOMレイアウトを変更します。
コンポーネント
Angularアプリケーションでは、ブラウザ(など)に表示されるものはコンポーネントです。コンポーネントは以下のパーツで構成されています。
- Componentクラスと呼ばれるTypeScriptのクラス
- コンポーネントのテンプレートと呼ばれるHTMLファイル
- コンポーネントのスタイルを指定するためのオプションの CSS ファイル。
- Componentクラスには、データとロジックが含まれています。
- HTMLテンプレートとスタイルでアプリ内のデータを表示します。ビューとも呼ばれ、ユーザーが対話するために画面上に表示されています。
- コンポーネントの振る舞いは、メタデータで定義します。コンポーネントのメタデータは @Component デコレータを使用してクラスに適用されます。コンポーネントの異なる振る舞いは、@Component デコレータの入力パラメータであるオブジェクトのプロパティとして渡すことができます。
コンポーネントとは、独自のテンプレートを持つディレクティブの一種です。Angularアプリケーションで表示されるものはすべてコンポーネントです。
コンポーネント・メタデータ
Componentデコレータは、クラスをコンポーネントとして装飾するものです。これは、オブジェクトをパラメータとして受け取る関数です。Componentデコレータでは、さまざまなプロパティの値を設定して、コンポーネントの振る舞いを設定することができます。最もよく使われるプロパティは、以下のとおりです。
- template
- templateUrl
- Providers
- styles
- styleUrls
- selector
- encapsulation
- changeDetection
- animations
- viewProviders
上記のものとは別に、いくつかの重要なプロパティがあります。それらを一つずつ見ていきましょう。
Angular の変更検知
Angularの変更検知とは何か」という質問に端的に答えると、「アプリの状態が変更されたかどうか、さらにDOMを更新する必要があるかどうかをAngularが確認するプロセス」となります。このプロパティは、コンポーネントに対してどのように変更検出が行われるかを決定します。このプロパティで、コンポーネントのChangeDetectionStrategyを設定します。設定可能な値は2つです。
- Default
- OnPush
このプロパティについては、以降のセクションで詳しく説明します。
カプセル化
このプロパティは、Angularがコンポーネントの Shadow DOMを作成するかどうかを決定します。これは、コンポーネントの ViewEncapsulation モードを決定します。3つの可能な値があります。
- Emulated (this is the default)
- Native
- None
- ShadowDom
コンポーネントの使用
コンポーネントは、Angularアプリケーションの中で様々な方法で使用することができます。
- ルートコンポーネントとして。
- 子コンポーネントとして。コンポーネント内で、別のコンポーネントを使うことができます。
- ルーティングを使用してコンポーネントに移動します。この場合、コンポーネントはRouterOutletに読み込まれます。
- ComponentFactoryResolverを使用してコンポーネントを動的にロードします。
コンポーネントは、モジュールの一部でなければなりません。モジュールの中でコンポーネントを使用するには、まずコンポーネントをインポートし、モジュールの宣言配列に渡します。
@NgModule({
declarations: [
AppComponent,
ProductComponent
]
})
スタンドアローンコンポーネント
Angular 14のリリースでは、スタンドアローンコンポーネントを構築することができ、それらはNgModuleで宣言する必要はありません。これらは独自の依存関係を管理し、別のスタンドアローンコンポーネントトを直接インポートすることができます。
次の方法で、スタンドアローンコンポーネントを作成することができます。
ng g c {componentName} --standalone
スタンドアロン・テンプレートで他のコンポーネント、ディレクティブ、パイプを使用したい場合、「standalone」フラグを設定することで、必要なものをスタンドアローンコンポーネント自体に直接インポートすることができます。
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-card', standalone: true, imports: [CommonModule], templateUrl: './card.component.html', styleUrls: ['./card.component.css'] })
export class CardComponent implements OnInit {
コントラクタ() {} ngOnInit(): void {} }
スタンドアローンコンポーネントは、Angularのエコシステムをフルに活用することができます。
Angularは多くの組み込みの構造ディレクティブと属性ディレクティブを提供しています。組み込みの構造的なディレクティブは *ngFor と *ngIf です。属性ディレクティブは、ngStyle と ngModel です。
Angular構造ディレクティブの使用
*ngIfは、実行される文に if 条件を与えるために使われる構造ディレクティブです。この式がFalseと評価された場合、その要素はDOMから削除されます。評価値がTrueの場合、その要素はDOMに追加されます。下のリストを見てください。この場合、*ngIfディレクティブは、showMessageプロパティの値がTrueであれば、DOMにdivを追加します。
@Component({
Selector: ‘app-message’, Template: ` < div *ngIf=”showMessage” >Show Message </div> ` })
export class AppMessageComponent {
showMessage = true;
}
ngIf は DOM 要素を隠したり表示したりしないことに留意してください。むしろ、条件によって追加したり削除したりします。
*ngFor構造ディレクティブは、ループでDOM要素を生成します。下のリストを見てください。この中で、*ngForディレクティブはデータ配列にある項目の数だけテーブルの行を追加します。
@Component({
Selector: ‘app-message’, Template: ` <table><tr *ngFor=’let f of data’><td>{{f.name}}</td></tr></table> ` })
export class AppMessageComponent {
data = [
{name : 'foo'},
{name: 'koo'}
];
}
ほとんどの場合、カスタムの構造ディレクティブを作成する必要はなく、組み込みのディレクティブで十分でしょう。
Angular Image ディレクティブ
ImageディレクティブはAngularのバージョン14.2で開発者プレビューとしてリリースされ、15.0からは安定版の一部になっています。NgOptimizedImageディレクティブは、画像の読み込みを最適化し、Largest Contentful Paint (最大視覚コンテンツの表示時間、LCP) を大幅に改善することができます。重要な画像を優先的に読み込み、優先度の低い画像はデフォルトで遅延ロードし、 タグに fetchpriority 属性を自動的に設定します。さらに、コードがベストプラクティスに沿っていることを確認するための警告も組み込まれています。利用可能なプロパティは次のとおりです。
- ngSrc - ローダによって処理され、srcプロパティに適用されるイメージの名前を含みます。
- ngSrcset - 幅と密度の記述子のリストを含みます
- width - ピクセル単位の画像の幅です
- height - ピクセル単位の画像の高さです。
- loading - タイプを定義します。これは、lazy、eager、autoのうちの1つです。
- priority - 画像を高い優先度で読み込むかどうかを示します。
NgOptimizedImage はスタンドアロンディレクティブで、コンポーネントに直接インポートするか、必要な ngModule にインポートすることができます。
import { NgOptimizedImage } from '@angular/common';
// スタンドアロンでないコンポーネントを使った例
NgModule({
imports: [NgOptimizedImage],})
class AppModule {}
// スタンドアロンコンポーネントの例
@Component({
standalone: true imports: [NgOptimizedImage], })
class StandaloneComponent {}
Angularのデータバインディングとは
データバインディングは、コンポーネントクラスとコンポーネントテンプレートの間でどのようにデータを流すかを決定します。これはデータをビューレイヤーにリンクさせる技術として使われます。Angularでのデータバインディングは簡単で、WPFと違ってデータコンテキスト、ビューモデル、INotifyPropertyChanged(INPC)などを気にする必要はありません。必要なのは、HTMLファイルとtypescriptファイルだけです。
Angularは3種類のデータバインディングを提供しています。
- 補間処理
- プロパティバインディング
- イベントバインディング
Angularの補間とは
Angularの補間は一方通行のデータバインディングです。コンポーネントクラスからテンプレートにデータを渡すために使用されます。補間の構文は {{propertyname}} です。
例えば、以下のようなコンポーネントクラスがあるとします。
export class AppComponent { product = {title: 'Cricket Bat', price: 500}; }.
コンポーネントクラスからテンプレートに製品を渡す必要があります。この例をシンプルにするために、productオブジェクトの値をハードコーディングしていることに留意してください。しかし、実際のシナリオでは、APIを使用してデータベースからデータを取得することができます。以下のリストに示すように、補間を使って商品オブジェクトの値を表示することができます。
<h1>製品</h1>
<h2>タイトル: {{product.title}}</h2>
<h2>価格: {{product.price}}</h2>
補間を利用し、データはコンポーネントクラスからテンプレートに渡されます。理想としては、商品オブジェクトの値が変更されるたびに、テンプレートが商品オブジェクトの更新された値で更新されることです。
Angularでは、change detector serviceという機能があります。これはコンポーネントクラスとテンプレートのプロパティの値が互いに同期していることを確認します。
そのため、Angularでデータを表示する場合は、補間データバインディングを使用する必要があります。
プロパティバインディング
Angularでは、プロパティバインディングと呼ばれる別のタイプのバインディングが用意されています。プロパティバインディングの構文は角括弧:[]で囲みます。これは、テンプレート上のHTML要素のプロパティをコンポーネントクラスから設定することができます。
そこで、以下のようなコンポーネントクラスがあるとします。
export class AppComponent {
btnHeight = 100; btnWidth = 100; }
これで、テンプレート上のボタンのheightとwidthのプロパティを、プロパティバインディングを使ってコンポーネントクラスのプロパティに設定することができるようになりました。
<button [style.height.px] = 'btnHeight' [style.width.px] = 'btnWidth' >商品を追加する</button>
Angularのプロパティバインディングは、HTML要素のプロパティをコンポーネントクラスのプロパティで設定するために使用されます。image、list、tableなど他のHTML要素のプロパティも設定することができます。コンポーネントクラスのプロパティ値が変更されるたびに、プロパティバインディングでHTML要素のプロパティが更新されます。
イベントバインディング
Angularはコンポーネントクラスのテンプレートで発生するイベントを捕捉するために、3つ目のタイプのバインディングを提供します。例えば、コンポーネントテンプレートにボタンがあり、コンポーネントクラス内の関数を呼び出すことができます。このような場合、イベントバインディングを使用します。イベントバインディングのシンタックスは、(eventname) です。
Angularの例では、このイベントバインディングのために、次のようなコンポーネントクラスがあります。
export class AppComponent {
addProduct() {console.log('add product');} }
テンプレート上のボタンがクリックされたときにaddProduct関数を呼び出したいと思います。これはイベントバインディングを使用して行うことができます。
<h1>製品</h1>
<ボタン (click)=’addProduct()’>製品を追加する</button>
Angularはこの3つのバインディングを提供しています。イベントバインディングではテンプレートからクラスへ、プロパティバインディングと補間ではクラスからテンプレートへデータが流れます。
Angularには双方向のデータバインディングが組み込まれていません。しかし、プロパティバインディングとイベントバインディングを組み合わせることで、双方向のデータバインディングを実現することができます。
Angularは双方向のデータバインディングを実現するためにngModelというディレクティブを用意しており、その使い方はとても簡単です。まず、FormsModuleをインポートして、双方向のデータバインディングを作成します。
export class AppComponent {
name = 'foo'; }
nameプロパティと入力ボックスの双方向のデータバインドを行うことができる。
<input type="text" [(ngModel)]='name' /> <h2>{{名前}}</h2>
ご覧のように、[(ngModel)]を使って、入力コントロールとnameプロパティの間に双方向のデータバインディングを作成しています。ユーザーが入力ボックスの値を変更するたびに、name プロパティは更新され、その逆も同様です。
パイプ
パイプとは、テンプレート内でデータを変換するために使用される関数です。Angularは組み込みのパイプのセットを提供しており、どのテンプレートでも使用することができます。
DatePipeは、日付を文字列にフォーマットします。
<p>StartDate: {{value | date: ‘dd/MM/yyyy’}}</p>
PercentagePipeは、値をパーセンテージに変換します。
value = 0.2;
…
<p>Percentage: {{value | percent}}</p> // 20%
文字列の大文字と小文字を区別する。
<p>小文字のテキスト: {{value | lowercase}}</p>
<p>大文字のテキスト: {{値| 大文字}}</p>
カスタムパイプの作成
ビルトインされていない特定の変換が必要な場合は、カスタムの変換を作成することができます。PipeTransform クラスを実装したクラスを作成し、そのロジックを transform メソッドに配置する必要があります。
import { Pipe, PipeTransform } from ‘@angular/core’;
@Pipe({name: ‘capitalize’})
export class CapitalizePipe implements PipeTransform {
//(キャピタライズパイプは、Pipe Transformを実装しています。
public transform(text: string): string {
return text[0].toUpperCase()+text.slice(1);
}
}
そして、それを使うためには、モジュール宣言に登録する必要があります。
コンポーネント通信
Angularでは、コンポーネント同士が通信を行い、オブジェクト、文字列、数値、配列、HTMLなどのデータを共有します。
コンポーネント通信を理解するためには、まず、コンポーネント間の関係を理解する必要があります。例えば、2つのコンポーネントが互いに関連していない場合、Angularサービスを通じて通信を行います。
あるコンポーネントを別のコンポーネントの内部で使用する場合、コンポーネント階層を作成することになります。他のコンポーネントの内部で使用されているAngularコンポーネントは子コンポーネントと呼ばれ、囲まれているコンポーネントは親コンポーネントと呼ばれます。下の画像のように、AppComponentのコンテキストでは、app-childが子コンポーネントで、AppComponentが親コンポーネントです。
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `<h1>Hello {{message}}</h1><app-child></app-child><!--child component-->)
export class AppComponent { //parent component message = '親です' }
親コンポーネントと子コンポーネントは、以下の方法でコミュニケーションをとることができます。
- @Input()
- @Output()
- Temp Ref Variable
- ViewChild
- ContentChild
コンポーネントが互いに関連していない場合、サービスを使用して通信します。それ以外の場合は、通信の条件に応じてさまざまなオプションのいずれかを使用して通信します。それでは、すべての選択肢を一つずつ見ていきましょう。
@INPUT
@Input デコレータを使用すると、親コンポーネントから子コンポーネントにデータを渡すことができます。データは、プリミティブ型の文字列、数値、オブジェクト、配列など、どのような形式でもかまいません。
@Inputの使い方を理解するために、コンポーネントを作ってみましょう。
import { Component } from '@angular/core';
@Component({
selector: 'app-child', template: `<h2> こんにちは {{greetMessage}}</h2>` })
export class AppChildComponent {
greetMessage = ‘私は子供です’; }
AppComponentはAppChildComponentを使っているので、AppComponentが親コンポーネントで、AppChildComponentが子コンポーネントです。データを渡すために、@Input デコレーターは、子コンポーネントのプロパティを使用します。そのためには、以下のリストのように、子コンポーネントであるAppChildComponentを修正する必要があります。
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-child',template: `<h2> こんにちは{{greetMessage}}</h2>`})
export class AppChildComponent implements OnInit {
@Input() greetMessage: string; constructor() {}ngOnInit() {} }
greetMessage プロパティを @Input() デコレータで修飾していることに注意してください。つまり、子コンポーネントでは greetMessage プロパティを @Input() デコレータで修飾し、親コンポーネントから greetMessage プロパティの値を設定できるようにしたのです。次に、親コンポーネントである AppComponent を修正して、子コンポーネントにデータを渡すようにしましょう。
import { Component } from '@angular/core';
@Component({
selector: 'app-root', template: ` <h2>Hello {{message}}</h2>` })
export class AppComponent {
message = '私は親です'; childmessage = '私は親から子コンポーネントに渡されます'; }.
親コンポーネントから、子コンポーネントのプロパティ greetMessage の値を設定しています。子コンポーネントに値を渡すには、角括弧の中に子コンポーネントのプロパティを渡し、その値を親コンポーネントの任意のプロパティに設定する必要があります。ここでは、親コンポーネントのchildmessageプロパティの値を子コンポーネントのgreetMessageプロパティに渡しています。
@OUTPUT
子コンポーネントから親コンポーネントへのイベントの発行は、@Output デコレータを使用します。
Temp Ref Variable
Angularでイベントバインディングを使用して双方向バインディングを実現する方法をご覧ください。@Outputを使用して、他のコンポーネントにイベントを発行します。AppChildComponentを以下のリストのように変更しましょう。
import { Component, Input, EventEmitter, Output } from '@ angular/core';
@Component({
selector: 'app-child', template: `<button (click)=”handleClick()”>Click me</button> ` })
export class AppChildComponent {.
handleClick() { console.log(‘hey I am clicked in child’);} }.
AppChildComponentのテンプレートの中に、関数handleClickを呼び出すボタンがあります。以下のリストのように、AppComponentの中にあるapp-childコンポーネントを使用してみましょう。
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root', template: `` })
export class AppComponent implements OnInit { ngOnInit() { } }
ここでは、AppComponentの中にAppChildComponentを使用しています。これにより、AppComponentが親で、AppChildComponentが子という親子関係を作っています。アプリケーションを実行すると、ブラウザのコンソールにこのメッセージが表示されます。
ここまで見てきたように、イベントバインディングを使って、ボタンがコンポーネント内の関数を呼び出すようにするのは非常に簡単です。さて、少し要件を変更してみましょう。AppChildComponent内のボタンのクリックイベントで、AppComponentの関数を実行したい場合はどうすればよいでしょうか。
そのためには、AppChildComponentからボタンクリックのイベントをemitする必要があります。EventEmitterとOutputを@angular/coreからインポートします。
ここでは、イベントを発生させ、そのイベントにパラメータを渡します。次のコードのように、AppChildComponentを修正します。
import { Component, EventEmitter, Output } from '@angular core';
@Component({
selector: 'app-child',template: `<button (click)=”valueChanged()”>Click me</button>`})
export class AppChildComponent {
@Output() valueChange = new EventEmitter(); counter = 0; valueChanged() { this.counter = this.counter + 1; this.valueChange.emit(this.counter); } }
AppChildComponentクラスでは、以下の作業を行いました。
- 発行されるイベントのパラメータとして渡されるcounterという変数を作成しました。
- 親コンポーネントに発信されるEventEmitter valueChangeを作成しました。
- valueChanged()という名前の関数を作成しました。この関数はボタンのクリックイベントで呼び出され、関数内部でvalueChangeというイベントが発せられます。
- valueChange イベントを発行する際に、カウンターの値をパラメータとして渡します。親コンポーネントであるAppComponentでは、以下のリストのように子コンポーネントであるAppChildComponentを使用することができます。
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root', template: `<app-child (valueChange)='displayCounter($event)'>` })
export class AppComponent implements OnInit {
ngOnInit() {} displayCounter(count) {console.log(count);} }
この段階で、AppComponentクラスでは、以下の作業を行っています。
- テンプレートで<app-child>を使用する。
- <app-child> 要素で、イベントバインディングを使用して、valueChangeイベントを使用する。
- valueChangeイベントでdisplayCounter関数を呼び出す。
- displayCounter関数で、AppChildComponentから渡されたカウンターの値を印字する
このように、AppChildComponentに配置されたボタンのクリックイベントで、AppComponentの関数が呼び出されます。これは、@OutputとEventEmitterで実現できます。アプリケーションを実行し、ボタンをクリックすると、ブラウザのコンソールにカウンターの値が表示されます。ボタンをクリックするたびに、カウンターの値は1ずつ増えていきます。
続きを読む
下記フォームをご入力の上、続きをお読みください。