2017.3.31
2017.4.17

ローディング状態(処理中)の表示

ファイルの読み込みや何かしらの時間のかかる処理だけでなく、いつもはすぐに終わる処理でも通信状態によってはレスポンスがなかなか帰ってこないといった場合があり、そういった時に画面になにも表示されないと動いているのかどうか分からずにボタンを連打されてしまうことがあるので、ロード中(処理中)には「裏でちゃんとやっていますよー」という状態を画面に表示するのは最近では必須になっていると思います。

たまにローディング状態になっているのに完全に止まっている場合がありますが、それはさておいて、複数の画面からロード中の表示切替を行う方法をメモしておきます。

ディレクトリ、ファイルの構成

今回、試してみたディレクトリ、ファイルの構成は以下の通りです。

project
├ node_modules
└ src
    └ app
        ├ app.component.ts
        ├ app.module.ts
        ├ app.state.ts
        └ example
            └ example.component.ts

コード

関係ないコードは省略しています。(Angularのチュートリアルがベース)

app.state.ts


import { Injectable } from '@angular/core';

@Injectable()
export class AppState {
  public loading: boolean = false;
  public loadStart(): void {
    this.loading = true;
  }
  public loadEnd(): void {
    this.loading = false;
  }
}

app.component.ts


import { Component } from '@angular/core';
import { AppState } from './app.state'

@Component({
  selector: 'my-app',
  styles: [`.loading{ position:fixed; top:10px; right:10px; width:80px; height:80px; z-index:10; }`],
  template: `
    ...
    <div class="loading" *ngIf="appState.loading">
      <img src="loading.gif" alt="Now Loading...">
    </div>
    ...
  `,
})
export class AppComponent {
  constructor(
    private appState: AppState
  ) { }
}

上記のコードはローディング用に作成したgif画像(Loader Generator - Ajax loader)を利用していますが、angular-materialのスピナー(Angular Material)を使ったりしてもいいかと思います。

app.module.ts


import { NgModule } from '@angular/core';
import { AppState } from './app.state';
import { AppComponent } from './app.component';
import { ExampleComponent } from './example/example.component';

@NgModule({
  ...
  declarations: [
    ...
    AppComponent,
    ExampleComponent
  ],
  providers: [
    AppState
  ],
  ...
})
export class AppModule { }

example.component.ts


import { Component } from '@angular/core';
import { AppState } from '../app.state'

@Component({
  selector: 'example',
  styles: [``],
  template: `
    <button (click)="search()">検索</button>
  `
})
export class ExampleComponent {
  constructor(
    private appState: AppState
  ) { }

  search(): void {
    this.appState.loadStart();
    // 時間のかかる処理
    xxx()
      .then(data => {
        this.appState.loadEnd();
      }).catch(error => {
        this.appState.loadEnd();
      });
  }
}

一回の処理に開始と終了の合計2行(または3行)のコードが必要になるので、もうちょっといい書き方ができないかとも思いますが、とりあえずはこれで。いい感じにできたら修正しておきます。

Angular】関連記事