Angular① – 基本

シェアする

前提の知識と環境

  • Node系の開発環境を構築できること
  • TypeScriptの知識があること
  • Angular6がインストールされていること
    (インストールをしていなければ、npm install g @angular/cli)

Angularは現在、6で構築される方が増えていますが、これまでのバージョンと違い、変わりました。といって基本ベースが変わったのではなく、従来の非推奨が消えたことおよび、ソースのチェックが厳しくなったので5までの経験者にとっては厄介な現象が起きています。

Angularが初めての人は、まずは、基本をしっかり押さえましょう。
従来あるソースをまねるだけではなく、知識を持ち、知恵をつけると、これまでのバージョンの相違などは吸収できます。

※検索をしてWebにあるソースは5までのもので6では利用できないことが多いので気を付けてください。

プロジェクトの作成は

プロジェクトを作成するディレクトリに移動して
ng new プロジェクト名

Angularの基本

Angularは、HTMLとTypeScriptでクライアントアプリケーションを開発するためのプラットフォームであり、そしてフレームワークです。
Angularはそれ自身がTypeScriptで書かれています。コア部分と、アプリケーションにインポートするオプショナルな機能をTypeScriptライブラリのセットとして実装しています。
Angularアプリケーションの基本となる構成要素は NgModule です。これは コンポーネント のコンパイルコンテキストを提供します。

上記の引用はAngularのドキュメントからです。現在、Angular 以外でも、TypeScriptを使用しています。簡単に言えば、TypeScriptを用いれば、いろいろなブラウザ仕様に合わせてJavaScriptに変換は可能です。
今、JavaScriptはES2015、ES2017の仕様が主流になっています。このような仕様の違いをカバーしているのがTypeScript です。

ではAngularはTypeScriptを用いてどのようにしているのでしょう。
Angularアプリケーションの基本となる構成要素は NgModule です。このNgModule で、Angular独自のコンパイルが働いています。つまり、Angularの作法に従って書けばアプリケーションが作成できます。

コンポーネントやサービスなどの用語は、実際にはPHPやJavaなどプログラム言語仕様で用いられているのでAngular 独自のものではありません。アプリケーションを構成する際に機能分担と再利用をしやすいように考えられたものです。ただ、Angular独自の仕様に影響している箇所も多数あるので、いろいろな経験を積んでいくと勘違いが発生します。
Angularの仕様をしっかり押さえましょう

コンポーネント

コンポーネントは ビュー を定義します。ビューは、プログラムのロジックとデータの中からAngularが選択し、変更できる画面要素のセットです。
すべてのアプリには、少なくともルートコンポーネントがあります。

コンポーネントは、ビューに直接関係しない特定の機能を提供する サービス を使用します。
サービスプロバイダーは、 依存性 としてコンポーネントに 注入 することができ、コードをモジュール化し、再利用可能で効率的にします。

コンポーネントは画面を構成します。サービスからデータを取得し、画面にデータを送ります。
画面とコンポーネント間とのデータの入出力は下記のテンプレートなどを参照してください。
コンポーネントは画面周りの制御に専念させるのがAugularの言語仕様です。

コンポーネントの見本

@ComponentがAngularのコンポーネント作成で、ログイン画面のテンプレートのHTMLを利用しています。
ngOnInitなどは、テンプレート上で発生するイベントを登録しています。
詳細な説明は後日の記事になります。
インターセプトやオブザーバの説明で利用しています。

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { first } from 'rxjs/operators';

import { AlertService, AuthenticationService } from '../_services';

@Component(
{ templateUrl: 'login.component.html' }
)
export class LoginComponent implements OnInit {
  loginForm: FormGroup;
  loading = false;
  submitted = false;
  returnUrl: string;

  constructor(
    private formBuilder: FormBuilder,
    private route: ActivatedRoute,
    private router: Router,
    private authenticationService: AuthenticationService,
    private alertService: AlertService) { }

  ngOnInit() {
    this.loginForm = this.formBuilder.group({
      username: ['', Validators.required],
      password: ['', Validators.required]
    });

    // reset login status
    this.authenticationService.logout();

    // get return url from route parameters or default to '/'
    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
  }

  // convenience getter for easy access to form fields
  get f() { return this.loginForm.controls; }

  onSubmit() {
    this.submitted = true;

    // stop here if form is invalid
    if (this.loginForm.invalid) {
      return;
    }

    this.loading = true;
    this.authenticationService.login(this.f.username.value, this.f.password.value)
      .pipe(first())
      .subscribe(
        data =>; {
          this.router.navigate([this.returnUrl]);
        },
        error => {
          this.alertService.error(error);
          this.loading = false;
        });
  }
}

モジュール

AngularのNgModuleは、アプリケーションドメイン、ワークフロー、あるいは一連の機能と密接に関連するコンポーネントセットのコンパイルコンテキストを宣言します。
NgModuleは、そのコンポーネントをサービスなどの関連コードをまとめて、機能単位を形成できます。
JavaScriptモジュールと同様に、NgModuleは他のNgModuleから機能をインポートし、独自の機能をエクスポートして他のNgModuleから使用できるようにします。たとえば、アプリでルーターのサービスを使用するには、RouterのNgModuleをインポートします。
コードを機能モジュールに組織することで、複雑なアプリケーションの開発や再利用性の設計を管理するのに役立ちます。

モジュール構成にする際、機能単位にして、開発を容易にできます。機能を分割するということです。
例えば、顧客管理などを集約したモジュールにすることがあります。
いろいろな分割方法がありますが、説明は割愛させていただきます。

モジュールの見本

下記は見本ソースです。@NgModuleがAngularのベースとなります。
説明などの詳細は後日になります。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';

・・・・

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    HttpClientModule,
    routing
  ],
  declarations: [
    AppComponent,
    AlertComponent,
    HomeComponent,
    LoginComponent,
    RegisterComponent
  ],
  providers: [
    AuthGuard,
    AlertService,
    AuthenticationService,
    UserService,
    { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },

    // provider used to create fake backend
    fakeBackendProvider
  ],
  bootstrap: [AppComponent]
})

export class AppModule { }

テンプレート、ディレクティブ、およびデータバインディング

テンプレートはHTMLと、HTML要素を表示する前に変更できるAngularマークアップを組み合わせています。
テンプレート ディレクティブ はプログラムロジックを提供し、 バインディングマークアップ はアプリケーションデータとDOMを接続します。

データバインディングには2種類あります:
イベントバインディング を使用すると、アプリケーションデータを更新することで、ターゲット環境のユーザー入力に応答できます。
プロパティバインディング を使用すると、アプリケーションデータから計算された値をHTMLに補間できます。

テンプレートにデータを入出力させる手段方法を提供しています。
テンプレートでは、HTMLを利用できますし、独自のタグを記入し、コンポーネントを利用して入出力させることも可能です。
デザインのCSSは通常のCSSが利用できますが、ファイルで提供されます。
例えば、
画面一覧の表示の場合は、サーバにあるデータを表示させる手段を提供していますし、
ログイン画面なら、ユーザー名やパスワードの入出力を提供しています。

ログイン画面の見本

ログイン画面の見本です。HTMLの中に見慣れないものがあるのがAngularになります。


<h2>ログイン画面</h2>


<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">

  
<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">ユーザ名は必須</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">パスワードは必須</div>

    </div>

  </div>

  
<div class="form-group">
    <button [disabled]="loading" class="btn btn-primary">Login</button>
    <a [routerLink]="['/register']" class="btn btn-link">Register</a>
  </div>

</form>

サービスと依存性の注入

特定のビューに関連付けられておらず、コンポーネント間で共有したいデータまたはロジックの場合は、 サービス クラスを作成します。
サービスクラスの定義は直前に@Injectable()デコレーターがあります。

画面には関係ないもの、DBのアクセスをコンポーネントに行わせるより、サービスを利用することによってDBアクセスを集中させて、メンテナンスを容易にさせる方法もあります。
共有データを持たせる場合など多くの利用方法があります。

ログの出力や、アラートの表示などは共通処理ですので、サービスで作成します。

ルーティング

AngularのRouter NgModuleは、アプリケーションのさまざまなアプリケーション状態とビュー階層の間でナビゲーションパスを定義できるサービスを提供します。
これは使い慣れたブラウザのナビゲーションの規約に基づいています。
アドレスバーにURLを入力すると、ブラウザが対応するページに移動します。
ページ上のリンクをクリックすると、ブラウザが新しいページに移動します。
ブラウザの前後のボタンをクリックすると、ブラウザはあなたが見たページの履歴を前後にナビゲートします。
ルーターはURLのようなパスをページの代わりにビューにマップします。

コンポーネント単位でルーティングが可能です。また機能の入れ替えも簡単にできることになります。
全体に影響を及ぼさずにルーティングが代えられます。機能の追加も可能です。

※一覧から詳細に変わる場合の、それぞれコンポーネントにし、ルーティングにすると、デザイン変更なども容易に行えます。
※メンテナンスを行いやすく拡張性を持たせることも重要です。

まとめ

今回の記事は概念です。今後、Angularについて詳細な記事になります。
Angularの頻繁なバージョンアップ、戸惑う人が多いでしょうが、これも解消すべき一つの解決策の説明になります。

シェアする

フォローする