らいふうっどの閑話休題

興味のあることをゆる~く書いていく

実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part1

実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part1

lacolaco さん監修の実践 Angular: Standalone Components をざっくりキャッチアップしてみます。 zenn.dev

Who is lacolaco? / lacolaco さんて、どんな人?
  • Google Developers Expert for Angular
  • Angularコントリビューター
  • Angular日本ユーザー会代表
  • jsprimer.net 著者

Zenn プロフィールから引用

記事内のAngular (NgModule-based minimal app) の構成は下記の通りです。

$ tree
.
├── angular.json
├── package.json
├── src
│   ├── global_styles.css
│   ├── index.html
│   └── main.ts 
└── tsconfig.json


■ 自分は、新規プロジェクト作成して実装してみました。

新規作成プロジェクトの場合の構成です。

$ ng new stand-alone-components-sample
$ cd stand-alone-components-sample 
$ tree
.
├── angular.json
├── package-lock.json
├── package.json
├── src
│   ├── app
│   │   ├── app.component.css
│   │   ├── app.component.html
│   │   ├── app.component.spec.ts
│   │   └── app.component.ts
│   ├── assets
│   ├── favicon.ico
│   ├── index.html
│   ├── main.ts
│   └── styles.css
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json

  • app.component.html の実装例

<h1>{{ title }}</h1>

  • app.component.ts の実装例

import 'zone.js/dist/zone.js';
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'stand alone components sample';
}

  • main.ts の実装例

import { AppComponent } from './app/app.component';
import { bootstrapApplication } from '@angular/platform-browser';

bootstrapApplication(AppComponent).catch((error) => console.error(error));

スタンドアロンコンポーネントを新規作成する手順

# スタンドアロンコンポーネント生成コマンド例

$ ng g c list --standalone # <== --standalone オプションを付ける
$ ng g c list-item --standalone

■ list と list-item コンポーネントを並列に生成した場合

$ tree
.
├── LICENSE
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── src
│   ├── app
│   │   ├── app.component.css
│   │   ├── app.component.html
│   │   ├── app.component.spec.ts
│   │   ├── app.component.ts
│   │   ├── list
│   │   │   ├── list.component.css
│   │   │   ├── list.component.html
│   │   │   ├── list.component.spec.ts
│   │   │   └── list.component.ts
│   │   └── list-item
│   │       ├── list-item.component.css
│   │       ├── list-item.component.html
│   │       ├── list-item.component.spec.ts
│   │       └── list-item.component.ts
│   ├── assets
│   ├── favicon.ico
│   ├── index.html
│   ├── main.ts
│   └── styles.css
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json


■ list と list-item のコンポーネントの並列配置の実装例(コンポーネントのみ)

  • app.component.html の実装例

<h1>{{ title }}</h1>

<app-list>
  <app-list-item><span>hoge</span></app-list-item>
  <app-list-item><span>fuga</span></app-list-item>
</app-list>

  • app.component.ts の実装例

import 'zone.js/dist/zone.js';
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';

import { ListComponent } from './list/list.component';
import { ListItemComponent } from './list-item/list-item.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, ListComponent, ListItemComponent],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'stand alone components sample';
}


■ list と list-item のコンポーネントを NgModule で実装した例

  • list.module.ts 追加

$ ng g m list
$ tree
.
├── LICENSE
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── src
│   ├── app
│   │   ├── app.component.ts
│   │   ├── list.module.ts # <== 追加
│   │   ├── list
│   │   └── list-item
│   ├── favicon.ico
│   ├── index.html
│   ├── main.ts
│   └── styles.css
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json

  • list.module.ts の実装例

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

import { ListComponent } from './list/list.component';
import { ListItemComponent } from './list-item/list-item.component';

@NgModule({
  imports: [ListComponent, ListItemComponent],
  exports: [ListComponent, ListItemComponent],
})
export class ListModule {}

  • app.component.html の実装例

<h1>{{ title }}</h1>

<app-list>
  <app-list-item><span>hoge</span></app-list-item>
  <app-list-item><span>fuga</span></app-list-item>
</app-list>

  • app.component.ts の実装例

import 'zone.js/dist/zone.js';
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';

import { ListModule } from './list.module';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, ListModule],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'stand alone components sample';
}

NgModule の方が、今までの実装の延長線上で理解できるので、分かり易かったです。


■ テンプレートの実装次第では、 list と list-item のコンポーネント構造を下図のように階層化すると実装が簡素になると思いました。

$ tree
.
├── LICENSE
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── src
│   ├── app
│   │   ├── app.component.css
│   │   ├── app.component.html
│   │   ├── app.component.spec.ts
│   │   ├── app.component.ts
│   │   ├── list
│   │   │   ├── list-item  # list の中に list-item を配置する
│   │   │   │   ├── list-item.component.css
│   │   │   │   ├── list-item.component.html
│   │   │   │   ├── list-item.component.spec.ts
│   │   │   │   └── list-item.component.ts
│   │   │   ├── list.component.css
│   │   │   ├── list.component.html
│   │   │   ├── list.component.spec.ts
│   │   │   └── list.component.ts
│   │   └── list.module.ts
│   ├── assets
│   ├── favicon.ico
│   ├── index.html
│   ├── main.ts
│   └── styles.css
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json


■ list と list-item コンポーネント構造が階層化されている場合の実装例

  • list.component.html の実装例

<app-list-item><span>hoge</span></app-list-item>
<app-list-item><span>fuga</span></app-list-item>

  • list.component.ts の実装例

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ListItemComponent } from './list-item/list-item.component';

@Component({
  selector: 'app-list',
  standalone: true,
  // list コンポーネント内で、list-item コンポーネントを定義
  imports: [CommonModule, ListItemComponent], 
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css'],
})
export class ListComponent {}

  • app.component.html の実装例

<h1>{{ title }}</h1>

<app-list></app-list> <!-- app-list タグのみ -->

  • app.component.ts の実装例

import 'zone.js/dist/zone.js';
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';

import { ListComponent } from './list/list.component';

@Component({
  selector: 'app-root',
  standalone: true,
  // ListComponent の実装だけで済む & ListModule が不要になります。
  imports: [CommonModule, ListComponent], 
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'stand alone components sample';
}

まとめ
関連記事
参考文献