Angular③ – コンポーネントの説明

シェアする

前回はAngularのモジュールの説明でした。
今回は、Angularのコンポーネントの説明です。
機能分割などをする際コンポーネントが重要な役割を果たします。

Angular6の基本です。基本的な事項は4以降はほぼ同じです。処理的なことは6で非推奨のものが増えました。 それに伴い、バージョン5まで使い方と違うものが増えました。また、コンパイルをする際のチェックが厳しくなり、5までの利用の仕方と違い戸惑う人が増えています。それらを解消するために一つの解決策を探ります。
Angular6です。基本的な事項は4以降はほぼ同じです。処理的なことは6で非推奨のものが増えました。 それに伴い、バージョン5まで使い方と違うものが増えました。また、コンパイルをする際のチェックが厳しくなり、5までの利用の仕方と違い戸惑う人が増えています。それらを解消するために一つの解決策を探ります。

最初に何をする?

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などのアクセスはサービスに任せます。
コンポーネントで画面に関係のない処理はサービス機能に分割することによって、不具合の発生を抑えます。

シェアする

フォローする