前回はAngularのモジュールの説明でした。
今回は、Angularのコンポーネントの説明です。
機能分割などをする際コンポーネントが重要な役割を果たします。
最初に何をする?
Angularでは何を作るのか?
機能や画面を洗い出して、構成を考えます。
例えば、
一覧コンポーネント、詳細画面コンポーネント
一覧や詳細を出すにはDBから情報を取得するサービスが必要となります。
一覧画面から詳細画面に遷移する場合、また、詳細画面から一覧画面に遷移する場合、ルーティングが必要です。
機能と画面周りをどの単位で分割するかはモジュール単位になります。
このように設計とコンポーネントなどの機能を洗い出します。
何すべきが決まれば実装はやりやすく、テストすべきこともわかります。
コンポーネントは画面のビューの役割があるので、デザインなども変更可能です。
コンポーネント
ユーザの登録コンポーネントを見本としてテンプレートなどの説明をします。
テンプレート
まずはテンプレートです。デザイナーにはなれないAngularのタグがあります。
一つの注意点としてはクラスでデザインをし、IDでデザインをしないことが必要です。
コンポーネントに分割されると、IDでは管理ができなくなります。
<h2>ユーザ登録/h2> <form [formGroup]="registerForm" (ngSubmit)="onSubmit()"> <div class="form-group"> <label for="lastName">姓</label> <input type="text" formControlName="lastName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.lastName.errors }" /> <div *ngIf="submitted && f.lastName.errors" class="invalid-feedback"> <div *ngIf="f.lastName.errors.required">Last Name is required</div> </div> </div> <div class="form-group"> <label for="firstName">名</label> <input type="text" formControlName="firstName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.firstName.errors }" /> <div *ngIf="submitted && f.firstName.errors" class="invalid-feedback"> <div *ngIf="f.firstName.errors.required">First Name is required</div> </div> </div> <div class="form-group"> <label for="username">ユーザ名</label> <input type="text" formControlName="username" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.username.errors }" /> <div *ngIf="submitted && f.username.errors" class="invalid-feedback"> <div *ngIf="f.username.errors.required">Username is required</div> </div> </div> <div class="form-group"> <label for="password">パスワード</label> <input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" /> <div *ngIf="submitted && f.password.errors" class="invalid-feedback"> <div *ngIf="f.password.errors.required">Password is required</div> <div *ngIf="f.password.errors.minlength">6文字以上です</div> </div> </div> <div class="form-group"> <button [disabled]="loading" class="btn btn-primary">Register</button> <a [routerLink]="['/login']" class="btn btn-link">Cancel</a> </div> </form>
HTMLのテンプレートです。Angular独自のタグがあります。
2行目:onSubmit()はHTMLのSubmitボタンに該当し、これはコンポーネントで説明します。
3行目から8行目が一つの項目です。
ngClass:エラーの場合に赤字にするためのCSSの設定をします。
*ngIf=:IF文です。ここではボタンが押されてエラーがある場合はエラー文言が表示されます。また必須 (required) にしているので空白の場合もエラーとなります。
ngが付くものはAngular独自のものですので、これはドキュメントを参照してください。
コンポーネント
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { first } from 'rxjs/operators'; import { AlertService, UserService } from '../_services'; @Component({ templateUrl: 'register.component.html' }) export class RegisterComponent implements OnInit { registerForm: FormGroup; loading = false; submitted = false; constructor( private formBuilder: FormBuilder, private router: Router, private userService: UserService, private alertService: AlertService) { } ngOnInit() { this.registerForm = this.formBuilder.group({ firstName: ['', Validators.required], lastName: ['', Validators.required], username: ['', Validators.required], password: ['', [Validators.required, Validators.minLength(6)]] }); } // convenience getter for easy access to form fields get f() { return this.registerForm.controls; } onSubmit() { this.submitted = true; // stop here if form is invalid if (this.registerForm.invalid) { return; } this.loading = true; this.userService.register(this.registerForm.value) .pipe(first()) .subscribe( data => { this.alertService.success('Registration successful', true); this.router.navigate(['/login']); }, error => { this.alertService.error(error); this.loading = false; }); } }
8行目:コンポーネントの定義で、利用するテンプレートを定義をする。
20~27行目:コンポーネントの初期化処理です。
ユーザ登録画面の姓などを初期化と、バリデーション宣言をする。
32~52行目:登録ボタンが押された時の処理を記述します。
ユーザサービスと登録の成功有無でアラート文言を変えています。
登録が成功すると、ログイン画面に遷移する(46行目)
subscribeの説明は後日にします。
ユーザサービスはサーバとのやり取りになります。成功すればdataに失敗すれば、errorの処理になります
コンポーネントには複雑な処理はいれず、処理はサービスとして分割し、再利用をしやすいようにしましょう。
まとめ
今回は登録コンポーネントでした。シンプルでしかも使いやすいように設計し、作成します。
コンポーネントの定義は、テンプレートのHTML、デザインのCSSが保守姓が重要です。複雑化させないように心がけましょう。
処理は、イベント単位に行います。
複雑な処理や、DBなどのアクセスはサービスに任せます。
コンポーネントで画面に関係のない処理はサービス機能に分割することによって、不具合の発生を抑えます。