SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

次世代Webアプリケーションフレームワーク「Angular」の活用

スタンドアロンコンポーネントと型付きリアクティブフォームに大注目!「Angular」バージョン14の新機能紹介

次世代Webアプリケーションフレームワーク「Angular」の活用 第26回

  • X ポスト
  • このエントリーをはてなブックマークに追加

 本連載では、Webアプリケーションフレームワーク「Angular」の活用方法を、サンプルとともに紹介しています。前回紹介したバージョン12・13に引き続き、今回は2022年6月にリリースされたバージョン14について、変更点や新機能を紹介していきます。

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめに

 Angularは、Googleとオープンソースコミュニティで開発されているJavaScriptフレームワークです。最初のバージョンはAngularJS(AngularJS 1)と呼ばれていましたが、バージョン2で全面的に刷新され、以降、おおむね半年に1回アップデートされています。

 2022年4月の前回記事では、2021年5月リリースのバージョン12と、同11月リリースのバージョン13について紹介しました。今回紹介するバージョン14(Angular 14)は、バージョン13から約半年後の2022年6月に、これまで通りのサイクルでリリースされました。本記事では、Angular 14で導入された主要な変更点や新機能を説明していきます。なお、全ての変更内容については、公式ドキュメントを参考にしてください。

対象読者

  • Angularの最新動向を定期的にチェックしておきたい方
  • 既存のAngularソースコードを最新版に追従する必要がある方
  • より便利にAngularを活用したい方

必要な環境

 Angularの開発では、一般にTypeScript(変換してJavaScriptを生成する、いわゆるAltJSの一種)が利用されます。本記事のサンプルコードもTypeScriptで記述しています。

 今回は以下の環境で動作を確認しています。

  • Windows 10 64bit版
  • Angular 14.0.4
  • Angular CLI 14.0.4
  • Node.js v16.15.1
  • Microsoft Edge 103.0.1264.44

 サンプルコードを実行するには、サンプルのフォルダーで「npm install」コマンドを実行してライブラリーをダウンロード後、「ng serve」コマンドを実行して、「https://localhost:4200」をWebブラウザーで表示します。

コンポーネントをモジュールから解放するスタンドアロンコンポーネント

 これまでAngularのコンポーネントは、モジュール(NgModule)の一部として扱われ、インポートもモジュール単位で行ってきました。Angular 14で導入された「スタンドアロンコンポーネント」では、モジュールを利用せずにコンポーネントを単体で実装できるようになります。なおAngular 14のスタンドアロンコンポーネントは「開発者プレビュー」なので、正式版では記述方法などが変更される可能性があります。

スタンドアロンコンポーネントの利用法

 図1のサンプルで、スタンドアロンコンポーネントの利用法を説明します。このサンプルは画面全体のAppComponent、リストの1行に対応するPhoneComponent、各行下部ボタンに対応するActionsComponentの3種のコンポーネントから構成されます。また、リストやボタンにはAngular MaterialのCard、Buttonコンポーネントを利用します。

図1 スタンドアロンコンポーネントのサンプル(p001-standalone)
図1 スタンドアロンコンポーネントのサンプル(p001-standalone)

 AppComponentでは、リスト1の<app-phone>でPhoneComponentを複数利用します。PhoneComponentにはname(名前)とvendor(メーカー)を指定します。

[リスト1]AppComponentのテンプレート(p001-standalone/src/app/app.component.html)

<app-phone name="Galaxy S22" vendor="Samsung"></app-phone>
<app-phone name="Reno7 A" vendor="OPPO"></app-phone>
<app-phone name="POCO F4 GT" vendor="Xiaomi"></app-phone>

 リスト1で利用されるPhoneComponentの実装はリスト2の通りです。

[リスト2]PhoneComponentの実装(p001-standalone/src/app/phone.component.ts)

@Component({
  selector: 'app-phone',
  standalone: true,   // スタンドアロンコンポーネントにする ...(1)
  imports: [          // コンポーネントへのインポート指定 ...(2)
    MatCardModule,    // 使用するモジュール ...(2a)
    ActionsComponent  // 使用する別のスタンドアロンコンポーネント ...(2b)
  ],
  templateUrl: './phone.component.html',
  styleUrls: ['./phone.component.css']
})
export class PhoneComponent {
  // コンポーネントへ渡される引数 ...(3)
  @Input() name = '';
  @Input() vendor = '';
}

 スタンドアロンコンポーネントにするには、(1)のstandaloneをtrueにします。また、従来モジュールで行っていたインポートの指定を、コンポーネントのimports(2)に記述します。このimportsには、使用するモジュールや別のスタンドアロンコンポーネントを指定します。ここでは(2a)でCardを含むAngular Materialのモジュール、(2b)でコンポーネントに含める別のスタンドアロンコンポーネントを指定しています。なお(3)はコンポーネントに渡される変数で、リスト1のname、vendor属性に対応します。

 (2b)で指定されているActionsComponent(actions.component.ts)も、リスト2と同様の記述でスタンドアロンコンポーネントにしています。詳細はサンプルコードを参照してください。

 最上位のコンポーネント(ルートコンポーネント)をスタンドアロンコンポーネントにすることもできます。standalone属性をtrueに設定してAppComponent(app.component.ts)をスタンドアロンコンポーネントにした後、起動処理を記述するmain.tsファイルを、リスト3の通り修正します。

[リスト3]スタンドアロンコンポーネントの起動処理(p001-standalone/src/main.ts)

// モジュールを起動する従来の処理 ...(1)
// platformBrowserDynamic().bootstrapModule(AppModule)
//   .catch(err => console.error(err));
// スタンドアロンコンポーネントを起動する処理 ...(2)
bootstrapApplication(AppComponent)
  .catch(err => console.error(err));

 従来は(1)の通り、モジュール(AppModule)を指定して起動していましたが、ルートコンポーネントがスタンドアロンコンポーネントの場合は(2)の通り、bootstrapApplicationメソッドにルートコンポーネントを指定して実行します。

フォーム記述を楽にする、型付きリアクティブフォーム

 スタンドアロンコンポーネントと並ぶAngular 14のトピックとして、「リアクティブフォームで型情報が有効になった」ことがあげられます。以下ではリアクティブフォームを大まかに説明した後で、型付きリアクティブフォームのメリットを紹介していきます。

Angularの「テンプレート駆動フォーム」と「リアクティブフォーム」

 Angularでは、「テンプレート駆動フォーム」と「リアクティブフォーム」の2種類のフォームが利用できます。テンプレート駆動フォームは、テンプレートに記述したフォームコントロールに[(ngModel)]ディレクティブを設定して、フォームの値をコンポーネントのプロパティに紐づけます(過去記事も参照してください)。コントロールの個数が少ない小規模なフォームに向いています。

 一方でリアクティブフォームでは、フォームとその構成要素を表すモデルを直接コンポーネントに記述して、テンプレート上のフォームと紐づけます。フォーム値の変更に反応して(リアクティブに)フォーム全体の値を受け取ったり、モデルを操作してフォームコントロールを動的に追加したりできます。コントロールの個数が多く複雑なフォームに向いています。

リアクティブフォームの例

 リアクティブフォームでコンポーネントにフォームモデルを記述するには、フォーム内のコントロール、そのグループ・配列を、FormControl、FormGroup、FormArrayに紐づけて記述します。図2のサンプルで説明します。

図2 リアクティブフォームのサンプル(p002-reactive-form)
図2 リアクティブフォームのサンプル(p002-reactive-form)

 図2のフォームは、リスト4の構造を持っています。

[リスト4]図2のテンプレート(p002-reactive-form/src/app/app.component.html)

<form [formGroup]="form"> <!--(1)-->
(略)
  <div>
    <input id="last-name" type="text" formControlName="lastName"> <!--(2)-->
  </div>
(略)
  <div formGroupName="address"> <!--(3)-->
    <div>
      <input id="pref" type="text" formControlName="pref">
    </div>
(略)
  </div>
(略)
  <div formArrayName="aliases"> <!--(4)-->
    <div *ngFor="let alias of aliases.controls; let i=index">
      <input id="alias-{{ i }}" type="text" [formControlName]="i">
    </div>
  </div>
(略)
</form>

 (1)の[formGroup]で、後述するリアクティブフォームの変数formを割り当てます。(2)ではformControlNameでフォームコントロール名を、(3)ではformGroupName属性でフォームグループ名を、(4)ではformArrayNameでフォーム配列名を割り当てています。

 リスト4に対応するリアクティブフォームの実装は、FormControl、FormGroup、FormArrayクラスのオブジェクトを利用してリスト5の通り行います。リスト4とリスト5は相似の階層構造を持っており、(1)~(4)がそれぞれ対応します。

[リスト5]リスト4に対応するリアクティブフォーム実装(p002-reactive-form/src/app/app.component.ts)

form = new FormGroup({           // ...(1)
  lastName: new FormControl(''), // ...(2)
(略)
  address: new FormGroup({       // ...(3)
    pref: new FormControl(''),
(略)
  }),
  aliases: new FormArray(        // ...(4)
    [new FormControl('')]
  )
});

 リスト4、5の通りリアクティブフォームの変数を定義してテンプレートのフォームと紐づけると、リスト6の通り、フォームやその内容を操作できるようになります。

[リスト6]リアクティブフォームを操作する処理(p002-reactive-form/src/app/app.component.ts)

// aliasesを取得するGetter ...(1)
get aliases() {
  return this.form.get('aliases') as FormArray;
}
// aliasesにフォームを追加 ...(2)
addAlias() {
  this.aliases.push(new FormControl(''));
}
// フォームに値を設定 ...(3)
updateProfile() {
  this.form.patchValue({
    lastName: '吉川',
    firstName: '英一',
(略)
  });
}

 (1)はフォームに含まれるaliasesをFormArrayとして取得するGetterメソッドです。これを利用して(2)では、aliasesに新たなFormControlを追加して、フォームにテキストボックスを動的に増やしています。また(3)では、form.patchValueメソッドを利用して、フォーム内の複数コントロールに一括で値を設定しています。

型付きリアクティブフォームのメリット

 リアクティブフォームで型情報が有効になったAngular 14では、リアクティブフォームの要素や型を、開発環境やコンパイラが認識します。例えばリスト6(3)の処理を記述する際に、要素の候補を表示できます。また、文字列が入るフォームに数字を代入しようとするとエラーが表示されます(図3)。

図3 型付きリアクティブフォームを活用する様子(p002-reactive-form/src/app/app.component.ts)
図3 型付きリアクティブフォームを活用する様子(p002-reactive-form/src/app/app.component.ts)

 なお、型情報がないリアクティブフォームを実装するには、UntypedFormGroup、UntypedFormControl、UntypedFormArrayクラスを利用します。サンプルコードに含まれるp002a-reactive-form-untypedサンプルでは、これらを利用して図2と同じフォームを実装しているので参考にしてください。このサンプルでは、図3に示した候補の表示や型不一致エラーの検出が行われません。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
開発者に気の利いた指摘をしてくれるExtended diagnotics

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
次世代Webアプリケーションフレームワーク「Angular」の活用連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16207 2022/07/25 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング