僕がAngularアプリケーションを書くときに頻出する実装パターンを紹介する記事です。続くかどうかは未定です。
onDestroy$
ngOnDestroy
メソッドが呼び出されたタイミングでemitされるEventEmitterを作っておき、RxJSのtakeUntil
パイプなどで使う実装パターン。
ngOnDestroy
メソッド内でunsubscribe
メソッドを呼び出すよりも宣言的で意味が取りやすいし、忘れにくい。
実装例はこんな感じ。ReactiveFormsModuleを使うときにvalueChanges
に引っ掛けることが多い。
import { Component, OnDestroy, OnInit, EventEmitter, Output } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-form', template: ` <form [formGroup]="form"> <input formControlName="name"> </form> ` }) export class FormComponent implements OnDestroy { @Output() valueChange = new EventEmitter<any>(); readonly form = new FormGroup({ name: new FormControl(), }); private readonly onDestroy$ = new EventEmitter(); constructor() { this.form.valueChanges .pipe( takeUntil(this.onDestroy$), ) .subscribe(value => { this.valueChange.emit(value); }); } ngOnInit() { this.form.patchValue({ name: 'Angular 5' }); } ngOnDestroy() { this.onDestroy$.emit(); } }
https://stackblitz.com/edit/angular-vdnrbp
MaterialModule
Angular Materialのモジュールを束ねるための中間モジュールを作るパターン。
使っているモジュールが一箇所でわかるのと、TestBed
に依存モジュールとして渡すのが楽になるので有用。
DI経由でグローバルに適用するAngular Materialの設定もここにまとめられるのでわかりやすい。
import { NgModule } from '@angular/core'; import { MatButtonModule, MatCardModule, } from '@angular/material'; import { PortalModule } from '@angular/cdk/portal'; import { OverlayModule } from '@angular/cdk/overlay'; export const modules = [ MatButtonModule, MatCardModule, OverlayModule, PortalModule, ]; @NgModule({ imports: [...modules], exports: [...modules], providers: [ { provide: MAT_LABEL_GLOBAL_OPTIONS, useValue: { float: 'always', }, }, ], }) export class MaterialModule {}
safeHtml
パイプ
これはみんな書くでしょ、って気がする。与えられた文字列を安全なHTMLですよ、とマーキングしてAngularに渡すお仕事。
import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; @Pipe({ name: 'safeHtml', }) export class SafeHtmlPipe implements PipeTransform { constructor(private sanitizer: DomSanitizer) {} transform(value: string): any { return this.sanitizer.bypassSecurityTrustHtml(value); } }
provideXXX
関数
サービスのプロバイダを関数としてエクスポートして、モジュール側で関数を呼び出すパターン。
何をprovideしているかがわかりやすい。
複数のサービスを一気にプロバイドする場合、特に順序が重要になるHTTP_INTERCEPTORS
のようなmulti
なプロバイダにおいて、モジュール側にそれを意識させずに済むのが気に入ってる。
export function provideHttpInterceptor() { return [ { provide: HTTP_INTERCEPTORS, useClass: AuthorizationHeaderInterceptor, multi: true, }, { provide: HTTP_INTERCEPTORS, useClass: CredentialInterceptor, multi: true, }, ]; }
import { provideHttpInterceptor } from './config/http'; @NgModule({ ... providers: [ provideHttpInterceptor(), ], }) export class CoreModule {}
書いてみるとそれほど種類がないなという気がしてきたので、次回は未定です。