PR

Angularとは?初心者Webエンジニア向けに10分でわかりやすく

WEBデザイン

Angularは、主にシングルページアプリケーション(SPA)の開発に特化したTypeScriptで書かれたフレームワークです。Googleが開発し、Googleを中心としたコミュニティの支援を受けているフレームワークの1つで、クライアントサイドのアプリケーションを効率的に構築、テスト、運用するための強力なツールを備えています。

Q
フレームワークとは?
A

フレームワークは、一言で表すと「Webサイトやアプリケーションを作るための道具箱」。フレームワークがあることで、プログラマーは難解なコードを1から書く必要なく、複雑なアプリケーションを効率的に開発することができます。

ポイント フレームワークが担う主な役割

  1. ルーティング
  2. データベースとのインターフェース
  3. テンプレートエンジン

これらの機能をフレームワークが提供してくれることで、開発者は複雑なWebアプリケーションも効率よく作成することができます。1から自分ですべてを作る必要がないので、必要な機能の開発にコストをかけることが可能。

ポイント おさえておきたい Angula の特徴

特徴説明
コンポーネントベースのアーキテクチャアプリケーションを再利用可能なコンポーネントに分割し、それぞれが独立して機能します。これにより、開発プロセスが簡素化されます。
TypeScriptJavaScriptのスーパーセットであり、型安全性や最新のECMAScript機能を提供します。大規模開発に適しています。
データバインディングモデルとビュー間で自動的にデータ同期を行う機能。一方向または双方向のデータバインディングをサポートします。
依存性注入コンポーネントやサービス間の依存関係を管理しやすくするための設計パターンを組み込んでいます。
モジュール性アプリケーションを機能モジュールに分割して、管理と再利用を容易にします。
豊富なビルトイン機能ルーティング、フォーム管理、HTTPクライアント、国際化など、開発に必要な基本的な機能が豊富に含まれています。

Angularとは?について↑これだけで説明しても何のことか全然ピンと来ないと思います。

ので、このページではAngularとは何か?をプログラマー向けにより具体的に各種サンプルコードを用いながらご説明していきます。Webエンジニア/Webデザイナーを目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。

参考 【JavaScript入門】基本文法/基礎文法を5分で

スポンサーリンク

Angularとは?

Angularとはシングルページアプリケーション(SPA)を構築するためのオープンソースのフロントエンドWebアプリケーションフレームワークです。TypeScript言語で書かれており、アプリケーションのスケールに関わらず、構造化された方法でコードを管理し、拡張することができます。

というのが概要。このページでは、実際にAngularの仕組みや開発方法がなんとなく理解できるようにするために、具体的にAngularの中身を深堀していきます。

Angularのプロジェクトは、特定のディレクトリ構造とファイルセットで構成されています。このディレクトリ構造といくつかのファイルが最初にAngularを理解するうえで非常に重要なので、初めに基本的なディレクトリ構成・ファイルの種類、およびそれらの関係性について説明します。

Angularの基本的なディレクトリ構造

プロジェクトルート
│
├── src/
│   ├── app/
│   │   ├── app.component.ts
│   │   ├── app.component.html
│   │   ├── app.component.css
│   │   └── {other components}/
│   │       ├── {component}.component.ts
│   │       ├── {component}.component.html
│   │       └── {component}.component.css
│   │
│   ├── assets/
│   │   └── {static files like images, fonts, etc.}
│   │
│   └── environments/
│       ├── environment.ts
│       └── environment.prod.ts
│
├── angular.json
└── package.json
  • src/: ソースファイルが格納される場所。アプリケーションのコンポーネントや静的アセットなど、開発に直接関連するファイルが含まれます。
    • app/: アプリケーションのコンポーネントが格納される場所。最初のapp.componentはアプリケーションのルートコンポーネントであり、その他のカスタムコンポーネントもここに配置します。
      • app.component.ts: コンポーネントのロジックを含むTypeScriptファイル。
      • app.component.html: コンポーネントのテンプレートを含むHTMLファイル
      • app.component.css: コンポーネント固有のスタイルを定義するCSSファイル
    • assets/: 画像やフォントなど、アプリケーションで使用される静的リソースを格納する場所。
    • environments/: 環境に応じた設定を管理。例えば、開発用と本番用の異なる設定をここで管理します。
  • angular.json: Angularプロジェクトの全体的な設定。プロジェクトのビルドやサーブの設定が含まれます。
  • package.json: プロジェクトの依存関係や使用するnpmスクリプトを定義します。このファイルはNode.jsのプロジェクトで一般的に使用されます。

ポイント ファイルの種類と内容

ファイルの拡張子内容説明
.ts (TypeScript)コンポーネントのクラス/ロジック/データモデルが定義される。Angularの多くの機能はこのTypeScriptを基にしている。
.htmlコンポーネントのテンプレートファイル。UI(ユーザーインターフェース)を構築するためのHTMLマークアップが含まれる。
.cssコンポーネント専用のスタイルシート。コンポーネントの見た目(スタイル)を定義。
Angularを構成する主要なファイル

この構造は、あくまでもAngularプロジェクトの基本的な骨格を示したもので、実際のプロジェクトでは追加のファイルやディレクトリが存在します。規模が大きくなるにつれ、ディレクトリの構造も大きくなっていきますが、とりあえずここではAngularの概要・骨格を明確にしていくために基本的な構造としての説明しておきます。

なんとなくの構造をみたところで、まずはAngular理解の最初のポイント「コンポーネント」について解説しておきます。

Angular:コンポーネントとは?

Angularにおける「コンポーネント」とは、アプリケーションのUI(ユーザーインターフェース)の一部を形成する再利用可能な構成要素のこと。

「部品」というイメージでOK。この「部品」を組み合わせて、様々な機能や画面を作り上げていくイメージ。

Angularのコンポーネントは、クラス(TypeScript)テンプレート(HTML)スタイル(CSS)の3つの主要な部分から構成され、これらが密接に連携して動作し1つの機能を実現します。ここではシンプルな例を用いて、それぞれの関連性と動作原理をご説明します。

Angularとは
図1:Angularの構造

クラス(TypeScript)

クラスはコンポーネントのデータ(状態)とロジック(振る舞い)を担当する部分です。TypeScriptを使用して定義され、コンポーネントの機能を実装します。クラスはアプリケーションのビジネスロジックをカプセル化し、プロパティとメソッドを通じてデータを保持および操作します。以下に、コンポーネントクラスの主要な構成要素と特徴について詳しく説明します。

クラスの構成要素

参考 Javascriptのクラスとは?

  1. プロパティ
    • コンポーネントの状態を保持。これらはテンプレート内で直接参照され、データバインディングを通じてビューに表示されるデータを提供します。
  2. メソッド
    • コンポーネントに関連する振る舞いやロジックを実装。ユーザーからのイベント応答(例えば、ボタンクリック)、データ処理、ビューの更新などを行います。
  3. ライフサイクルフック
    • Angularはコンポーネントのライフサイクルの特定の時点で実行されるメソッドを提供します。これには、コンポーネントの初期化、ビューとデータの更新、コンポーネントの破棄などが含まれます。

上記「データバインディング」については後ほど詳しくご説明します。

コンポーネントクラスの定義

コンポーネントクラスは@Componentデコレーターで修飾され、Angularに対してこれがコンポーネントであることを示します。このデコレーターは、セレクタ、テンプレートURL、スタイルURLなど、コンポーネントに関連するメタデータを指定します。

サンプル example.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent {
  // プロパティ: コンポーネントのデータを保持
  title = 'Hello World';

  // メソッド: コンポーネントのロジックを実装
  greet() {
    console.log('Hello!');
  }
}

TypeScript(ts)ファイルは、主に以下の部分から構成されます。

1. インポート文

Angularコアライブラリやその他必要なモジュール、コンポーネント、サービスなどから、必要な機能やデータ型をインポートします。

import { Component } from '@angular/core';

2. @Componentデコレーター

@Componentデコレーターは、クラスがAngularコンポーネントであることを示し、コンポーネントのメタデータを設定します。メタデータには、セレクタ(テンプレート内でこのコンポーネントを識別するための名前)、使用するテンプレートファイルのパス、およびコンポーネント専用のスタイルファイルのパスが含まれます。

@Component({
  selector: 'app-example', // コンポーネントのセレクター
  templateUrl: './example.component.html', // テンプレートへのパス
  styleUrls: ['./example.component.css'] // スタイルシートへのパス
})

3. コンポーネントクラス

コンポーネントの振る舞いを定義するクラスです。OnInit(初めて呼び出されるタイミング)というように、ライフサイクルフックを実装することができます。クラス内では、コンポーネントのプロパティやメソッドを定義し、テンプレートからアクセスできるようにします。

export class ExampleComponent {
  // プロパティ: コンポーネントのデータを保持
  title = 'Hello World';

  // メソッド: コンポーネントのロジックを実装
  greet() {
    console.log('Hello!');
  }
}

ライフサイクルフックとは?

ライフサイクルフックとは、ライフサイクル(初期・変更がなされたとき・処理が終了するとき)の特定の時点で実行されるメソッドのこと。これらのフックを使用することで、開発者はコンポーネントの初期化、変更検出、破棄などのプロセスに介入し、カスタムロジックを適用することができます。ライフサイクルフックは、アプリケーションのパフォーマンスを向上させたり、リソースのクリーンアップを行う際に特に有用です。

ライフサイクルフック説明
ngOnInitコンポーネントの初期化時に実行されます。コンポーネントが作成された後、最初の変更検出が行われる前に呼び出されます。データバインディングの初期化やコンポーネントの初期データフェッチに適しています。
ngOnChanges入力プロパティ (@Input) の値が変更されたときに実行されます。コンポーネントの初期化時や、入力プロパティが外部から変更された場合に呼び出されます。変更検出の前後でデータの更新を行う場合に有効です。
ngDoCheckAngularがデータ変更を検出した後、自動的に実行されるngOnChangesに加えて、カスタム変更検出ロジックを実行するために呼び出されます。
ngAfterContentInitコンポーネントのビューまたは子コンポーネントが初めて初期化された後に実行されます。コンテンツ投影(<ng-content>を通したコンテンツ)が初期化された後に呼び出されます。
ngAfterContentCheckedAngularがコンテンツ投影されたコンポーネントの内容をチェックした後に、各変更検出サイクル後に実行されます。
ngAfterViewInitコンポーネントのビューと子ビュー、またはディレクティブが初期化された後に実行されます。DOM操作や子コンポーネントの初期化後の操作に適しています。
ngAfterViewCheckedコンポーネントのビューと子ビューのチェックが完了した後、各変更検出サイクル後に実行されます。
ngOnDestroyコンポーネントが破棄される直前に実行されます。リソースの解放や、イベントリスナーの削除など、クリーンアップ作業に適しています。

Angularのコンポーネントクラスは、そのコンポーネントの核となる部分です。ビューを表示するためのデータと、ユーザーのインタラクションに応答するためのロジックを定義。クラスを通じて、アプリケーションの振る舞いを細かく制御し、必要に応じてデータを加工や更新が可能です。

続いて、コンポーネントの2つ目の部品「テンプレート」とそれに関する「データバインディング」について解説します。

テンプレート(HTML)

テンプレートは、コンポーネントのユーザーインターフェース(UI)を定義するHTMLの部分です。テンプレートは、データバインディング、およびテンプレート参照変数などのAngularの特殊構文を利用して、動的なビューを作成することができます。テンプレートを通じて、コンポーネントのクラスに定義されたデータとロジックをユーザーが操作できる形に表示し、ユーザーからの入力に反応します。

サンプル example.component.html

<div>
  {{ message }} <!-- データバインディングを使用して、クラスのmessageプロパティを表示 -->
</div>

このテンプレートはmessageプロパティの値を表示します。プロパティの値が変更されると、表示も自動的に更新されます。

データバインディング

Q
データバインディングとは?
A

データバインディングとは、Webアプリケーションにおいて、HTML(テンプレート)とTypeScript(コンポーネントクラス)の間でデータを同期させるプロセスのこと。Angularでは、この機能を使ってコンポーネントのデータとビューを簡単に連携させることができます。データバインディングを利用することで、プログラムのロジックとUIが密接に結びつき、データの変更が自動的にUIに反映されるようになります。

サンプル データバインディング

<div>
  <input [(ngModel)]="newTask" placeholder="新しいタスクを入力" /> <!-- 双方向データバインディング -->
  <button (click)="addTask()">タスクを追加</button> <!-- クリックイベントのバインディング -->

  <ul>
    <li *ngFor="let task of tasks">{{ task }}</li> <!-- タスクリストの表示 -->
  </ul>
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'app-task-list',
  templateUrl: './task-list.component.html',
  styleUrls: ['./task-list.component.css']
})
export class TaskListComponent {
  tasks: string[] = []; // タスクを保持する配列
  newTask: string = ''; // 新しいタスクの入力値をバインドするためのプロパティ

  addTask() {
    if (this.newTask) {
      this.tasks.push(this.newTask); // 新しいタスクをリストに追加
      this.newTask = ''; // 入力フィールドをリセット
    }
  }
}
バインディングタイプ構文説明
補間{{ expression }}コンポーネントのプロパティや式の値をテンプレートのテキストとして表示します。式の評価結果がテキストとしてDOMに挿入されます。
プロパティバインディング[target]="expression"コンポーネントのプロパティや式の値をHTML要素のプロパティにバインドします。これにより、要素の属性を動的に変更できます。
イベントバインディング(target)="statement"HTML要素のイベント(例: click)が発生したときに、コンポーネントのメソッドやステートメントを実行します。
双方向バインディング[(ngModel)]="property"コンポーネントのプロパティとフォーム要素(例: input)の値を双方向にバインドします。これにより、ユーザー入力とコンポーネントの状態が同期されます。

テンプレート参照変数

テンプレート参照変数は、AngularにおいてHTMLテンプレート内の要素に名前を付け、その要素への参照を得るために使用される変数です。これにより、テンプレート内で直接、HTML要素のインスタンスにアクセスすることが可能になります。テンプレート参照変数は、特にフォーム要素やDOM操作が必要な場合に便利です。

参考 DOMとは?

テンプレート参照変数を宣言するには、HTML要素内で#記号の後に変数名を指定します。この変数は、宣言された要素のコンテキスト内、またはその要素を含むテンプレート内で使用できます。

以下の例では、<input>要素にテンプレート参照変数#emailInputを割り当てています。この変数を使用して、ボタンクリック時にその<input>要素の値(ユーザーが入力したメールアドレス)をコンソールに表示するイベントを設定しています。

<input type="text" #emailInput placeholder="Enter your email">
<button (click)="logValue(emailInput.value)">Log email value</button>
export class AppComponent {
  logValue(value: string) {
    console.log(value);
  }
}

テンプレート参照変数は、フォームの値を取得する、特定のDOM要素にアクセスする、子コンポーネントのメソッドやプロパティにアクセスするなど、多様な用途で利用されます。これにより、Angularアプリケーションのテンプレート内でよりダイナミックでインタラクティブな挙動を実装することが可能になります。

スタイル(CSS)

スタイルでは、コンポーネントの見た目を定義します。スタイルはコンポーネントにローカルに適用され、他のコンポーネントには影響を与えません。

サンプル example.component.css

div {
  color: red; /* テキストの色を赤に設定 */
}

このCSSはテンプレートのdiv要素に適用され、テキストの色を赤にします。

まとめ Angularの構成要素

  • クラスはデータとロジックを管理し、テンプレートはそのデータを表示する方法を定義。データバインディングにより、クラスのプロパティが変更されるとテンプレートに自動的に反映される。
  • スタイルはテンプレートの見た目をカスタマイズ。これらはコンポーネントにスコープされ、コンポーネントの隔離を保つ。

これらの3つの要素が有機的に結合することで、1つの画面・機能ができあがっているということをまずは押さえておきましょう。

参考 HTML CSS JavaScriptの違い

サンプル:コンポーネント

サンプル ユーザー名を表示するコンポーネント

コンポーネントの理解を深めるために、Angularにおけるコンポーネントの組み込み方法と3つのファイル(TypeScriptクラス、HTMLテンプレート、CSSスタイル)の関連性を、さらに別のサンプルコードを使って詳しく説明します。

1:TypeScriptクラスファイル: コンポーネントの定義:user.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-user', // コンポーネントのセレクター
  templateUrl: './user.component.html', // テンプレートファイルへのパス
  styleUrls: ['./user.component.css'] // スタイルファイルへのパス
})
export class UserComponent {
  userName = 'John Doe'; // テンプレートで表示するためのユーザー名
}

このTypeScriptファイルでは@Componentデコレータを使用して、コンポーネントのメタデータ(セレクタ、テンプレートURL、スタイルURL)を定義し、コンポーネントクラスUserComponentuserNameプロパティを定義しています。

2:HTMLテンプレートファイル: UIの定義:user.component.html

<div class="user">
  User Name: {{ userName }}
</div>

HTMLテンプレートファイルでは、データバインディングを使用してTypeScriptクラスのuserNameプロパティを表示しています。

3:CSSスタイルファイル: コンポーネントのスタイル定義:user.component.css

.user {
  color: blue;
  font-weight: bold;
}

CSSスタイルファイルでは、テンプレートの.userクラスに対してスタイルを定義しています。

Angular:セレクタ(Selector)

Angular理解のための第2ステップが「セレクタ」です。

セレクタ(Selector)は、コンポーネントをHTMLテンプレート上で識別するための名前です。@Componentデコレーター内で定義されたセレクタを使うことで、他のコンポーネントのテンプレートやアプリケーションのメインHTMLファイル内にコンポーネントを埋め込むことができるようになります。

Angularのセレクタ
図2:Angularのセレクタ

セレクタはコンポーネントをHTML上で識別・配置するためのキーとして機能します。実際にセレクタを利用することでどんなことができるのか?をクラスの実装から~HTMLへの埋め込みまでを順を追ってご説明します。

ステップ1:コンポーネントクラスの作成

コンポーネントを作成します。

import { Component } from '@angular/core';

@Component({
  // この部分でセレクタを定義します
})
export class MyComponent {
  // コンポーネントのデータとメソッド
}

ステップ2:セレクタの定義

コンポーネントクラスのデコレーター@Component内で、selectorプロパティを使用してセレクタを定義します。セレクタは通常、カスタムHTMLタグとして表されます。

@Component({
  selector: 'app-my-component', // セレクタを定義
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponent {
  // コンポーネントのデータとメソッド
}

ここで定義したapp-my-componentセレクタです。これにより、コンポーネントは<app-my-component></app-my-component>という形式でHTMLテンプレート内に埋め込むことができます。

ステップ3:HTMLテンプレートへのコンポーネントの配置

セレクタを使用して、Angularアプリケーションの任意のHTMLテンプレート(アプリケーションのメインHTMLファイル、他のコンポーネントのテンプレートなど)にコンポーネントを配置できます。

<!-- app.component.html -->
<div>
  <!-- MyComponentをHTMLテンプレートに埋め込む -->
  <app-my-component></app-my-component>
</div>

このようにして配置されたコンポーネントは、指定した位置でレンダリングされ、そのコンポーネントのテンプレートが表示されます。

ポイント セレクタ(Selector)とは?

  • セレクタはコンポーネントをHTMLテンプレートに組み込むための識別子として機能。
  • コンポーネントクラスで@Componentデコレーターを用いてセレクタを定義し、そのセレクタをHTMLタグとして使用することで、アプリケーションの任意の場所にコンポーネントを配置できる。

セレクタの形式

セレクタのタイプ形式例使用方法例
エレメントセレクタselector: 'app-my-component'<app-my-component></app-my-component>
属性セレクタselector: '[app-my-component]'<div app-my-component></div>
クラスセレクタselector: '.app-my-component'<div class="app-my-component"></div> (非推奨)
  • エレメントセレクタ: これは最も一般的なセレクタの形式で、カスタムHTMLタグとしてコンポーネントを指定。これによりHTMLテンプレート内で直接コンポーネントを埋め込むことができるようになります。
  • 属性セレクタ: この形式ではコンポーネントがHTML要素の属性として指定されます。これにより、既存のHTMLタグに追加の機能を組み込むことができ、柔軟なテンプレート設計が可能になります。
  • クラスセレクタ: CSSクラスにマッチするセレクタですが、Angularのコンポーネントにおいては一般的ではありません。クラスセレクタは主にスタイリングのために使用され、コンポーネントのセレクタとして使用することは推奨されていません。

ここまでの説明を踏まえて先ほどのサンプルを再度見てみましょう。

1:TypeScriptクラスファイル: コンポーネントの定義:user.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-user', // コンポーネントのセレクター
  templateUrl: './user.component.html', // テンプレートファイルへのパス
  styleUrls: ['./user.component.css'] // スタイルファイルへのパス
})
export class UserComponent {
  userName = 'John Doe'; // テンプレートで表示するためのユーザー名
}

2:HTMLテンプレートファイル: UIの定義:user.component.html

<div class="user">
  User Name: {{ userName }}
</div>

app.component.html (アプリケーションのメインページのテンプレート)

<div>
  <h1>Welcome to the Angular App!</h1>
  <app-user></app-user> <!-- UserComponentがここに展開されます -->
</div>

以下のような関連図が頭の中で描けていればあなたの理解は大体OK!

図2:コンポーネントの関連

まとめ セレクタとは?

セレクタはHTMLテンプレート内の特定の要素を識別するための名前やパターンです。CSSで言うところのクラスセレクタやIDセレクタに似ていますが、AngularではコンポーネントやディレクティブをHTML要素に適用するために使用されます。

  • エレメントセレクタ: app-my-componentのように、カスタムHTMLタグとして定義します。<app-my-component></app-my-component>とHTMLに記述することで、このタグに対応するAngularのコンポーネントやディレクティブが適用されます。
  • 属性セレクタ: [appHighlight]のように、角括弧を使用して定義します。<div appHighlight></div>とHTML要素に記述することで、この属性に対応するディレクティブがその要素に適用されます。

Angular:ディレクティブ

次に、Angularの重要概念「ディレクティブ」についてご説明します。

ディレクティブは、HTML要素の振る舞いを変更するための命令や指示です。これにより、要素に新しい機能を追加したり、表示を動的に制御したりできます。

ディレクティブという概念を論理的に分解して説明すると、Angularではディレクティブは大きく分けて2種類:構造ディレクティブ属性ディレクティブの2つに分けることができます。これらはコンポーネントと似ていますが、役割と使用方法が異なります。

構造ディレクティブと属性ディレクティブ

Angularにおける構造ディレクティブ属性ディレクティブは、HTML要素の振る舞いを変更するために使用される特別なマークアップですが、その目的と動作原理に違いがあります。以下で、それぞれのディレクティブの使い方と動作原理をご説明します。

構造ディレクティブ

構造ディレクティブは、DOMの構造を変更することができます。これは、要素を追加したり削除したりすることによって行われます。

動作原理: 構造ディレクティブは、通常、*プレフィックスを使用してテンプレート上で適用されます。これにより、Angularはディレクティブの存在する要素をラップする<ng-template>を自動的に作成し、その内容の表示を制御することができます。

使用例  *ngIf*ngFor

*ngIfディレクティブを使用して条件に応じて要素を表示/非表示にします。

<!-- 条件が真の場合のみ<p>タグを表示します -->
<p *ngIf="condition">条件が真のときに表示されます</p>

参考 HTML:pタグ

*ngForディレクティブを使用して配列の各アイテムに対して要素を繰り返し表示します。

<!-- 配列itemsの各アイテムに対して<li>タグを繰り返し表示します -->
<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

参考 ulタグ / liタグ

カスタム構造ディレクティブ

カスタム属性ディレクティブとは、開発者が定義する属性ディレクティブの一種。標準の属性ディレクティブ(例えば、ngStylengClass)以外に、アプリケーションの特定の要求に応じた特別なロジックやスタイリングを適用する必要がある場合に、カスタム属性ディレクティブを作成します。

ポイント カスタム属性ディレクティブの作成ステップ

  1. ディレクティブクラスの作成
    • Angular CLIのコマンドng generate directive my-directiveを使用するか、手動でディレクティブクラスを作成します。ディレクティブのデコレーター@Directiveには、セレクターが指定され、このセレクターはディレクティブが適用される属性を識別します。
  2. ロジックの実装
    • ディレクティブクラス内に、要素の外見や振る舞いを変更するロジックを実装します。ElementRefを使用してディレクティブが適用されるDOM要素にアクセスし、Renderer2を使って要素のスタイルやプロパティを安全に変更します。
  3. アプリケーションのモジュールにディレクティブを宣言
    • 作成したディレクティブをアプリケーションのモジュール(通常はAppModule)のdeclarations配列に追加します。

サンプル highlight.directive.ts (カスタム属性ディレクティブ)

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor(private el: ElementRef) {}

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight('yellow');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string | null) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

app.component.htmlappHighlightディレクティブを使用する方法

<div appHighlight>This text will be highlighted when hovered over.</div>

カスタム属性ディレクティブを作成することで、アプリケーションの再利用可能なロジックやビジュアルエフェクトを効率的に管理できるようになります。

属性ディレクティブ

属性ディレクティブは、要素の外見や振る舞いを変更するために使用されますが、要素の追加や削除は行いません。

動作原理: 属性ディレクティブは、要素の属性として適用され、その要素のプロパティや属性、スタイルを動的に変更します。これにより、要素の外見やDOM上での振る舞いを制御できます。

使用例 ngStylengClass

ngStyleディレクティブを使用して、要素のスタイルを動的に適用します。

<!-- スタイルオブジェクトに基づいて動的にスタイルを適用 -->
<div [ngStyle]="{'font-size': size + 'px'}">テキストサイズを動的に変更</div>

ngClassディレクティブを使用して、条件に応じてクラスを動的に適用します。

<!-- 条件が真の場合に'special'クラスを適用 -->
<div [ngClass]="{'special': isSpecial}">特別なスタイルを適用</div>

これらのディレクティブを利用することで、Angularアプリケーション内のHTML要素の外見や振る舞いを柔軟に制御することができます。構造ディレクティブと属性ディレクティブは、それぞれDOMの構造変更と要素のプロパティ/スタイルの変更という異なる目的で使用され、アプリケーションのUIをよりダイナミックにするために重要な役割を果たします。

コンポーネントは特別なディレクティブ

Angularでは、コンポーネントもディレクティブの一種として取り扱われます。コンポーネントもHTML要素の振る舞いを変更するための命令や指示を行うという意味で最も一般的な形態のディレクティブであると言えます。

しかし、コンポーネントはテンプレート(HTMLビュー)を持つ点が特徴で、アプリケーションのUI部品(画面の一部分やページ全体など)を構築するために使われるという点で異なります。

コンポーネントとディレクティブの違いを理解するための鍵は、その役割にあります。コンポーネントはアプリケーションのUI部分を構築するためのものであり、テンプレート(ビュー)とロジック(クラス)を持ちます。一方で、構造ディレクティブと属性ディレクティブは既存の要素に対して特定の動作やスタイルを適用するためのもので、直接的にビューを持つわけではありません。

ポイント コンポーネントディレクティブ

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<h1>Welcome to {{title}}!</h1>
             <app-highlight>This text will be highlighted.</app-highlight>
             <div *ngIf="show">This text is conditionally shown.</div>
             <div [ngStyle]="{color: 'blue'}">This text is styled blue.</div>`,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Angular Directives';
  show = true;
}

このように考えると、コンポーネントはアプリケーションの構築ブロックとしての「部品」であり、ディレクティブは既存のHTML要素やコンポーネントに追加の振る舞いやスタイルを与えるための「ツール」や「装飾」と理解することができます。この区別を理解することで、Angularのアーキテクチャをより深く理解し、効果的に利用することが可能になります。

ディレクティブとセレクタ

ディレクティブとセレクタの関係性が良くわからなくなる方もいるので、ここでディレクティブとセレクタの関係性について補足しておきます。

分かりやすく説明すると。セレクタが「アプリを開くアイコン」のような役割をしているとすれば、この「アプリ」に相当するのがディレクティブだと説明できます。

ディレクティブは「スマートフォンのアプリ

ディレクティブを、スマートフォンにインストールできる「アプリ」と考えてみましょう。このアプリは、スマートフォン(HTML要素)に追加された時に特定の機能を提供します。例えば、写真を編集するアプリ(属性ディレクティブ)、天気をチェックするアプリ(コンポーネントディレクティブ)、あるいはスケジュール管理を助けるアプリ(構造ディレクティブ)などがあります。

セレクタは「アプリを開くアイコン

セレクタは、そのアプリ(ディレクティブ)をどのスマートフォンの画面(HTMLテンプレート内の要素)に表示するかを指定する「アイコン」と考えることができます。ホーム画面に配置されたアイコンをタップすると、関連するアプリが起動します。同様に、HTMLテンプレート内で特定のセレクタ(アイコン)を使うと、対応するディレクティブ(アプリ)がその要素に適用され、特定の機能が動作するようになります。

まとめ コンポーネント vs ディレクティブ vs セレクタ

コンポーネント

  • what is?: コンポーネントは、テンプレート(HTML)、スタイル(CSS)、およびビジネスロジック(TypeScriptクラス)をカプセル化した、再利用可能なUI部品。
  • 役割: アプリケーションのビューの一部を構成します。ユーザーインターフェースを構築するために使用されます。
  • : <app-example></app-example>のように、カスタムHTMLエレメントとしてテンプレート内で使用されます。

ディレクティブ

  • what is?: ディレクティブは、HTML要素の振る舞いを変更したり、新しい振る舞いを追加したりするための指令。コンポーネント以外に、構造ディレクティブと属性ディレクティブの2種類があります。
  • 役割:
    • 構造ディレクティブ: DOMの構造を変更します(例: *ngIf, *ngFor)。
    • 属性ディレクティブ: 要素の外見や振る舞いを変更しますが、構造は変えません(例: [ngStyle], [ngClass])。
  • : <div *ngIf="isVisible"></div><div [ngStyle]="{color: 'red'}"></div>など。

セレクタ

  • what is?: セレクタは、コンポーネントやディレクティブをHTMLテンプレート内の特定の要素に適用するために使用される、識別子やパターン。
  • 役割: Angularがテンプレートを解析する際に、どの要素に対して特定のコンポーネントやディレクティブを適用するかを指示します。
  • : selector: 'app-example'(コンポーネント)、selector: '[appHighlight]'(属性ディレクティブ)、selector: '.app-example-class'(クラスセレクタ、一般的ではない)。

ポイント 違いと関連性

  • コンポーネントはディレクティブの特殊な形態であり、より構造化されたUI部品を構築するために使用されます。
  • ディレクティブは、構造や外見を変更するためのより汎用的なツールです。
  • セレクタは、これらのコンポーネントやディレクティブがどのHTML要素に適用されるかを決定するために使われます。

つまり、コンポーネントとディレクティブは「何をするか」に関するものであり、セレクタは「どこにそれを適用するか」に関するものです。ディレクティブ(コンポーネントを含む)はセレクタを使用してHTML要素に結びつけられます。

Angular:サービス

ここからはサービスとは何か?についての解説に移ります。

Angularにおけるサービスとは、一言で説明すると特定の機能を提供するためのクラスです。データの取得、データの管理、ビジネスロジックの処理などが含まれたクラスをサービスと呼び、サービスクラスは、@Injectable()デコレーターを使用して定義されます。このデコレーターはAngularの依存性注入システムでサービスを利用可能にします。

「依存性注入システム」については後ほどご説明します。

サービスの定義方法

  • サービスクラスの定義
    • @Injectable()デコレーターを使用して、サービスとして機能するクラスを定義します。このデコレーターはクラスをサービスとしてマークし、Angularの依存性注入システムがこれを認識できるようにします。
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root' // このサービスはアプリケーションのルートインジェクターによって提供される
})
export class ExampleService {
  constructor() { }
  // サービスのメソッド
}

サービスが作成されたら、それをアプリケーションの他の部分から利用できるようにする必要があります。Angularでは、サービスを提供する方法がいくつかあります。

パターン1 providedIn: 'root'を使用する

サービスの@InjectableデコレーターにprovidedIn: 'root'オプションを設定すると、サービスはアプリケーション全体でシングルトンとして利用できます。これにより、サービスのインスタンスは必要に応じて自動的に作成され、アプリケーションのどこからでも同じインスタンスにアクセスできます。

@Injectable({
  providedIn: 'root'
})

パターン2 モジュールのproviders配列に追加する

サービスを特定のモジュールのみで利用したい場合は、そのサービスをモジュールのproviders配列に追加します。これにより、そのモジュールとそのモジュールで宣言されたコンポーネントでのみサービスが利用可能になります。

@NgModule({
  providers: [ExampleService]
})

パターン3 コンポーネントレベルで提供する

特定のコンポーネントとその子コンポーネントでのみサービスを利用したい場合は、コンポーネントのproviders配列にサービスを追加します。これにより、サービスの新しいインスタンスがコンポーネントごとに作成されます。

@Component({
  providers: [ExampleService]
})

サービスの利用

サービスを提供した後、コンポーネントや他のサービスからそれを利用できます。サービスを利用するには、通常、コンポーネントのコンストラクタにサービスを注入します。

constructor(private exampleService: ExampleService) { }

このプロセスを通じて、Angularアプリケーションにおいてサービスが中心的な役割を果たし、データ管理やビジネスロジックを効率的に扱うことができるようになります。サービスの提供方法を適切に選択することで、アプリケーションの設計の柔軟性と保守性が向上します。

依存性の注入(Dependency Injection, DI)

依存性の注入(Dependency Injection, DI)は、ソフトウェア設計のパターンの1つであり、コンポーネントやクラスの依存関係を外部から供給する手法です。この手法の目的はコードの結合度を低減しモジュール性を向上させ、テストのしやすさを高めることにあります。AngularではこのDIパターンがコア機能の1つとして深く組み込まれています。

文章による説明だけでは分かりづらいと思うので、早速コードを見てみましょう。

依存性の宣言: クラスはコンストラクター内で必要な依存性を宣言します。

constructor(private http: HttpClient) { }

依存性の提供: アプリケーションのモジュールまたはコンポーネントで、利用可能な依存性とそのプロバイダーを宣言します。

@NgModule({
  providers: [MyCustomService]
})
依存性の注入をわかりやすく

あなたがカフェに行き、コーヒーを注文するとします。通常、自分でコーヒーを淹れるためには豆を挽き、お湯を沸かし、コーヒーを淹れるなど、いくつかのステップを踏む必要がありますが、カフェではこれらの準備をすべてバリスタ(コーヒーの専門家)が行ってくれます。あなたは単に「コーヒーをください」と注文するだけで、準備された美味しいコーヒーを受け取ることができます。

DIの説明:

  • 自分でコーヒーを淹れる = 自分のクラスで直接依存性(他のクラスやライブラリ)を作成・管理する
  • バリスタにコーヒーを淹れてもらう = 依存性の注入を使って、必要な機能やデータを外部から受け取る

依存性の注入の動作原理:

  1. 依存性の宣言: あなたがカフェでコーヒーを注文するとき、何が必要か(コーヒー、ミルク、砂糖など)を告げます。プログラミングにおいて、これはクラスがコンストラクタを通じて必要とする依存性を宣言することに相当します。
  2. 依存性の提供: カフェでは、バリスタがコーヒーを淹れる準備をしています。同様に、プログラムでは、AngularのDIシステムが必要な依存性のインスタンスを提供します。
  3. 依存性の注入: カフェで注文した通りにコーヒーが提供されるように、プログラムでは、DIシステムがコンストラクタに必要な依存性を注入します。

要は、自分で必要なものを持ってくるのではなく、バリスタ(DIシステム)が必要なものを持ってきてくてくれる仕組みが、依存性の注入ということです。

Angular:モジュール(Module)

Angularのモジュールについて、初心者向けに基本から説明します。Angularでいう「モジュール」とは、.tsファイル(TypeScriptファイル)で定義される関連するコンポーネントやサービス、ディレクティブ、パイプなどをグループ化したものです。これらのモジュールを通じて、アプリケーションの機能を組織的に管理することができます。

要は、モジュールは先ほど説明したコンポーネントをまとめたものである、と理解すればOKです。

例えば、ユーザー管理機能、商品管理機能など、1つの機能に関連する要素をひとつのモジュールとしてまとめることができます。もしくは、再利用可能なコンポーネントやサービスを別のモジュールとして分割して、他のアプリケーションやモジュールからも利用できるようにしたりする目的でまとめるのが一般的です。

ポイント モジュールの役割

  1. 機能のカプセル化
    • モジュールはアプリケーションの特定の機能や機能群をカプセル化します。これにより、アプリケーションをより管理しやすく、再利用しやすい構成要素に分割することができます。
  2. 再利用性の向上
    • 関連するコンポーネントやサービスをモジュールとしてまとめることで、そのモジュールを他のアプリケーションでも再利用できるようになります。
  3. 遅延ローディングのサポート
    • 特定のモジュールを必要とするタイミングまでロードを遅らせる(遅延ローディング)ことができ、アプリケーションの起動時間の短縮に役立ちます。

モジュールの定義方法

Angularでモジュールを定義するには、@NgModuleデコレータを使用します。このデコレータは、モジュールのメタデータを指定するために使われ、Angularにモジュールの存在とその内容を教えます。

サンプル アプリケーションのルートモジュール (app.module.ts)

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
// 他のインポート...

@NgModule({
  declarations: [
    AppComponent,
    // 他のコンポーネント...
  ],
  imports: [
    BrowserModule,
    // 他のAngularモジュール...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  • declarations: このモジュールに属するコンポーネント、ディレクティブ、パイプを宣言します。
  • imports: 他のモジュールのクラスが必要とする場合、そのモジュールをここにインポートします。例えば、ブラウザでアプリケーションを実行するためにはBrowserModuleが必要です。
  • providers: サービスのプロバイダーを登録します。これにより、アプリケーションのどの部分からでもサービスを利用できるようになります。
  • bootstrap: アプリケーションが起動する際に最初にロードされるコンポーネントを指定します。通常、これはアプリケーションのルートコンポーネントです。

このWebサイトは現役のエンジニアが以下3点を目的として運営しています。

  1. 勉強:一度理解した内容を忘れないように。
    → アウトプットは「最強のインプット」である! 
  2. 備忘:忘れたとしても後から見返せるように。
    → 未来の自分への「お手紙」を書いています。 
  3. 共有:〇〇ってこうだったんだ!の感動をシェアできるように。
    → あなたの知識は誰かにとっての「価値ある情報」です。 

副業ブログの始め方はこちらから

スポンサーリンク
WEBデザイン
シェアする
ビズドットオンラインをフォローする
タイトルとURLをコピーしました