PR

Angular:ディレクティブとは何か?初心者向けにわかりやすく3分で解説

TypeScript

Angularでよく耳にする「ディレクティブ」という概念は、一言でいうと「HTML要素に特別な振る舞いや制御を付与するための拡張機能」です。

このページでは、そもそもディレクティブって何?という人向けにディレクティブのイメージ・本質的な理解が進むように1からわかりやすく使い方や注意点を解説していきます。

スポンサーリンク

まずはディレクティブのイメージをつかむ

たとえば、普通のHTMLでは<div><p>などの要素をただ書いただけでは、そこに特別な「動き」はありません。テキストを表示したり、見出しを表現したりするだけです。

そこに「この要素は、ある条件が満たされたら表示し、そうでなければ非表示にしたい」とか、「ある配列のデータをもとに、同じ形の要素を繰り返し表示したい」といった動的な振る舞いを付けたくなる場面が出てきます。

Angularにおいては、この「動的な振る舞い」をHTML要素に追加するための仕組みこそがディレクティブです。ディレクティブを使うと、HTMLタグをただ書くだけでなく、「この要素はどう表示されるのか」「いつレンダリングされるのか」といった命令を付け加えることができます。

JavaScriptでのDOM操作との違い

従来のJavaScriptでDOM(参考 DOMとは?)を直接操作する場合には、以下のようなステップが必要でした。

  1. JavaScriptでdocument.getElementById()などを使い、特定の要素を取得する。
  2. その要素のstyle.displayを操作して表示/非表示を切り替えたり、クラスを付けたり、テキストを変更したりする。
  3. 条件が変わるたびに、この要素のDOM操作をもう一度書く。

こうした処理を複数のHTML要素に対して行うと、コード量が増えメンテナンスが煩雑になります。さらに、「UI側(HTML)の定義」と「JavaScript側(ロジック)の処理」が分散してしまうため、「どこで何をやっているのか」がわかりにくくなる、という課題が出てきます。

一方で、Angularのディレクティブを使うと、HTMLのテンプレートに「表示するときはこうする」という命令(ディレクティブ)を組み込めるので、UIとロジックの関連が見えやすく、構造を把握しやすいという利点があります。

「HTMLに命令を埋め込む」という発想

ディレクティブはHTML側に命令を埋め込むようなイメージで考えると理解しやすくなります。「ここにもしデータがあったら繰り返し表示する」「ここの条件がtrueなら、このブロックを描画する」といった振る舞いを、HTMLタグの属性として書けるのです。

  • 例: *ngIf="isVisible"
    • isVisibleという変数がtrueのときだけ要素が表示される
  • 例: *ngFor="let item of items"
    • items配列をひとつずつ取り出して要素を繰り返し生成する

こうしたディレクティブをHTMLに貼り付けるだけで、Angularはテンプレートを解釈し、内部的にDOMを追加/削除したり、表示/非表示の切り替えを行ってくれます。

コンポーネントとの違いをざっくり知る

Angularを学び始めると、ディレクティブとほぼ同時に「コンポーネント」という言葉を耳にするはずです。コンポーネントも広い意味では「ディレクティブの一種」とされますが、次のような違いがあります。

  • コンポーネント
    • HTMLテンプレート、TypeScriptのクラス、CSSスタイルなどをひとまとめにした「画面の部品」
    • <app-○○>のような独自タグとして使うことが多い
  • ディレクティブ(構造・属性ディレクティブなど)
    • 画面の見た目そのものではなく、既存のHTML要素の振る舞いだけを拡張する命令書のようなイメージ
    • *ngIf*ngForのような構造ディレクティブ、[ngClass]のような属性ディレクティブが代表例

このようにコンポーネントとディレクティブは、どちらも「AngularがHTMLをどう解釈して動的に扱うか」を制御していますが、コンポーネントは「見た目のかたまり」を構成するのに対し、ディレクティブは「特定の振る舞いを要素に追加する」という役割に特化しているというイメージを持つと、両者を使い分けやすくなります。

ディレクティブがもたらすメリット

  1. HTMLテンプレートに直接“動き”を宣言できる
    • *ngIf*ngForを見れば、一目で「ここの要素が条件付き表示/繰り返し表示なんだ」と理解できる。
  2. コードの可読性・メンテナンス性の向上
    • 画面遷移や表示切り替えといったロジックを、HTML側と直接リンクさせて書けるため、可読性が上がる。
  3. 複雑なDOM操作の削減
    • もしディレクティブがなければ、JavaScriptでDOM操作のAPIを使って要素の追加削除を毎回行う必要があるが、その分の処理をAngular側が肩代わりしてくれる。

こうしたメリットから、AngularのディレクティブはアプリケーションのUIをより動的かつ宣言的に構築できる重要な機能だと言えます。

このようにディレクティブの本質は「HTML要素をベースに、より複雑な処理を記述できる拡張機能」として存在していることにあります。単純なHTMLの延長線として考えられるので、初心者の方でも慣れてくると「ここで*ngIfを使えばいいのか」「繰り返し表示には*ngForを使うんだな」と自然に使いこなせるようになるでしょう。

ディレクティブの種類

Angularでは、多彩な動きをHTML要素に追加できるディレクティブですが、大きく分けて3つのカテゴリーに分類されます。ここでは、それぞれの特徴や使い方をイメージしやすいように、順を追って解説していきます。

1. コンポーネント(Component Directive)

  • 何をする?
    • 画面(UI)を構成する最小単位の部品を定義するためのディレクティブです。
    • 独自のHTMLテンプレート、CSSスタイル、そして振る舞い(TypeScriptクラス)をまとめて管理します。
  • どんなイメージ?
    • 「ボタン」「カード」「ユーザー情報パネル」のように、ひとかたまりのUI要素として切り出したいときに使います。
    • <app-xxx> のような独自タグが作られて、テンプレート内で再利用できるようになります。
  • なぜ便利?
    • テンプレートやロジックが分離されずに一体化して管理できるため、開発・保守がしやすい。
    • コードの再利用やチーム開発時の分担がやりやすくなる。

コンポーネントはディレクティブの一種

技術的には、コンポーネント(@Component)もディレクティブ(@Directive)の拡張版として位置付けられています。ただし、コンポーネントが「UIのひとかたまり」であるのに対して、構造・属性ディレクティブは「UIの見た目や構造を変化させるための命令書」という位置づけです。

2. 構造ディレクティブ(Structural Directive)

  • 何をする?
    • HTMLの要素を「追加・削除」して、DOM(画面構造)自体を変化させるためのディレクティブです。
  • どんなイメージ?
    • 「条件がtrueのときだけ要素を表示したい」「配列の要素を繰り返し表示したい」など、動的に要素を増減する仕組みが必要なときに使います。
  • なぜ便利?
    • 従来ならJavaScriptでDOM操作をして要素を手動で増やしたり削除したりしていた部分を、テンプレートの記述だけで表現できる。
    • 画面ロジックがHTML上で明確にわかるので、可読性も高い。

サンプルコード1 *ngIfと*ngFor の併用

<div *ngIf="items && items.length > 0">
  <ul>
    <li *ngFor="let item of items">{{ item }}</li>
  </ul>
</div>

要素が存在して、かつ1つ以上アイテムがある場合にのみ、リストを表示する構造を簡潔に表現できます。構造ディレクティブは、*プレフィックスを使用してテンプレート上で適用されます。これにより、Angularはディレクティブの存在する要素をラップする<ng-template>を自動的に作成し、その内容の表示を制御することができます。

サンプルコード2 *ngIfを使用して条件に応じて要素を表示/非表示にする

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

サンプルコード3 *ngForディレクティブを使用して配列の各アイテムに対して要素を繰り返し表示

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

カスタム属性ディレクティブとは、開発者が定義する属性ディレクティブの一種。標準の属性ディレクティブ(例えば、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>

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

3. 属性ディレクティブ(Attribute Directive)

  • 何をする?
    • 既存のHTML要素やコンポーネントに対して、見た目や振る舞いを変更するための追加機能を付与するディレクティブです。
    • “HTMLタグそのものの構造を増減する”のではなく、“そのタグの属性やスタイルなどを動的に操作する”イメージです。
  • どんなイメージ?
    • 「ある条件でクラスを切り替えたい」「スタイルを動的に変更したい」など、要素の属性に関わる部分をAngularの仕組みと連動させたいときに活躍します。
  • なぜ便利?
    • 画面のデザインや動的変化をコード内のロジックと直接リンクできるので、UIの変更がわかりやすい。
    • Sassなどのスタイル管理とも相性がよく、UIの動的変更を細かく制御できます。

代表的な属性ディレクティブ

  1. [ngClass]
    • 条件に応じてクラスを追加・削除したり、複数のクラスを同時に切り替えたりできる。
    • 例: [ngClass]="{ 'active': isActive, 'error': hasError }"
  2. [ngStyle]
    • スタイルをオブジェクト形式で動的に変更できる。
    • 例: [ngStyle]="{ 'background-color': bgColor }"
  3. [ngModel]
    • フォーム要素(入力欄など)とデータをバインドするために使う。(Template-driven formsで利用)
  4. その他カスタム属性ディレクティブ
    • Angularが用意しているディレクティブ以外にも、自分で作成して要素の見た目や挙動を拡張できます。

サンプルコード4 ngClass の使用例

<button 
  [ngClass]="{ 'btn-primary': isPrimary, 'btn-disabled': isDisabled }">
  ボタン
</button>

サンプルコード5 ngStyleディレクティブを使用して要素のスタイルを動的に適用

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

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

まとめ ディレクティブ

  • コンポーネント:画面の部品(HTMLテンプレートとスタイル、振る舞いのセット)。
  • 構造ディレクティブ:HTMLの構造を動的に増やしたり減らしたり(*ngIf*ngFor など)。
  • 属性ディレクティブ:要素のクラスやスタイルなどを動的に変化させる([ngClass][ngStyle] など)。

これら3つの役割をしっかり把握すると、「どのタイミングでどのディレクティブを使うのか」「表示するUIパーツはコンポーネントにまとめる」「要素の表示切り替えやクラスの変更は構造・属性ディレクティブで行う」といった使い分けが自然にできるようになります。結果として、コードの可読性や再利用性が高まり、大きなアプリケーションでも管理しやすいUI構造を作れるようになるでしょう。

タイトルとURLをコピーしました