実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part2
lacolaco さん監修の実践 Angular: Standalone Components をざっくりキャッチアップしてみます。 zenn.dev
- Google Developers Expert for Angular
- Angularコントリビューター
- Angular日本ユーザー会代表
- jsprimer.net 著者
Zenn プロフィールから引用
前回
■ 2 種類のインジェクターがあるそうです。
■ 新規に service を作って理解してみる
$ cd src/app/list $ ng g s list # list.servce.ts の作成 $ ng g i list # list.servce.ts 用の interface の作成 $ cd ../../../ $ 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.component.css │ │ ├── list.component.html │ │ ├── list.component.spec.ts │ │ ├── list.component.ts │ │ ├── list.service.spec.ts # 新規作成 │ │ ├── list.service.ts # 新規作成 │ │ └── list.ts # 新規作成 │ ├── assets │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ └── styles.css ├── tree.txt ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json
- list.ts
export interface List { name: string; }
- list.service.ts
import { Injectable } from '@angular/core'; import { List } from './list'; @Injectable({ providedIn: 'root', }) export class ListService { constructor() {} get(): List[] { // 単純な List[] を返すだけ return [{ name: 'hoge' }, { name: 'fuga' }]; } }
■ service を component, html に反映します。
- list.component.ts
import { Component, OnInit, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Observable, filter, of } from 'rxjs'; import { ListItemComponent } from './list-item/list-item.component'; import { ListService } from './list.service'; import { List } from './list'; @Component({ selector: 'app-list', standalone: true, imports: [CommonModule, ListItemComponent], templateUrl: './list.component.html', styleUrls: ['./list.component.css'], + // ListService を依存注入(DI) + providers: [{ provide: ListService, useClass: ListService }], }) export class ListComponent implements OnInit { list: List[] = []; - // これまでの実装 - constructor(private service: ListService) {} + // スタンドアロンコンポーネント用の依存注入(DI) + readonly service = inject(ListService); + constructor() {} ngOnInit(): void { this.list = this.service.get(); } }
- list.component.html
- <app-list-item><span>hoge</span></app-list-item> - <app-list-item><span>fuga</span></app-list-item> + <app-list-item *ngFor="let item of list"> + <span>{{ item.name }}</span> + </app-list-item>
■ HttpClient を DI してみます。
[{ "name": "hoge" }, { "name": "fuga" }]
- main.ts
import { bootstrapApplication } from '@angular/platform-browser'; + import { provideHttpClient } from '@angular/common/http'; import { AppComponent } from './app/app.component'; - bootstrapApplication(AppComponent).catch((error) => console.error(error)); + bootstrapApplication(AppComponent, + { + providers: [provideHttpClient()], + } + ).catch((error) => console.error(error));
- list.service.ts を HttpClient 使った実装にします。
import { Injectable, inject } from '@angular/core'; + import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { List } from './list'; @Injectable({ providedIn: 'root', }) export class ListService { - // これまでの実装 - constructor(private http: HttpClient) {} + // 依存注入(DI)します。 + readonly http = inject(HttpClient); + constructor() {} - get(): List[] { - return [{ name: 'hoge' }, { name: 'fuga' }]; - } + // HttpClient 実装に変更します。 + get(): Observable<Array<List>> { + return this.http.get<Array<List>>('./assets/json/list.json'); + } }
- list.component.ts
import { Component, OnInit, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Observable, filter, of } from 'rxjs'; import { ListItemComponent } from './list-item/list-item.component'; import { ListService } from './list.service'; import { List } from './list'; @Component({ selector: 'app-list', standalone: true, imports: [CommonModule, ListItemComponent], templateUrl: './list.component.html', styleUrls: ['./list.component.css'], providers: [{ provide: ListService, useClass: ListService }], }) export class ListComponent implements OnInit { - list: List[] = []; + // 戻り値の型が Observable になったので、コンポーネントのプロパティの型も変更 + list$: Observable<List[]> = of([]); readonly service = inject(ListService); constructor() {} ngOnInit(): void { - this.list = this.service.get(); + // 戻り値の型が Observable になったので、コンポーネントのプロパティの型も変更 + this.list$ = this.service + .get() + .pipe(filter((list) => !!list && list.length > 0)); } }
- list.component.html
- <app-list-item *ngFor="let item of list"> + <!-- データバインドの型が Observable になったので、async を実装 + <app-list-item *ngFor="let item of list$ | async"> <span>{{ item.name }}</span> </app-list-item>
まとめ
provideHttpClient()
関数を定義するのと依存注入(DI)の実装の仕方を覚えるだけで基本的には良いようです。- ルーティング のキャッチアップは次回に続きます。
関連記事
- 実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part1
- 実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part2
- 実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part3
- 実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part4
- 実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part5
- 実践 Angular: Standalone Components をざっくりキャッチアップしてみた Part6(まとめ)
参考文献