2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Angular Material で、処理中のスピナーに進捗%をテキスト表示する

Last updated at Posted at 2021-02-21

はじめに

Angular Material の Progress Spinner で進捗%をテキスト表示したのだが、意外とハマったので備忘録として作成。
やりたいことは以下の画像のようにしたいだけだが、テキスト表示を追加するにはコンポーネントを自作しないといけないっぽい。

image.png

デザインなどは別途修正するとして、とりあえず必要最低限のコードだけ抜粋。

コンポーネント

まずはコンポーネントを作成する。
html, ts, scssの3セット。

progressSpinner.component.html
<mat-progress-spinner
  mode="indeterminate"
  diameter="100"
  strokeWidth="8"
>
</mat-progress-spinner>
<div class="message">{{ message }}</div>
progressSpinner.component.ts
import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-progress-spinner',
  templateUrl: './progressSpinner.component.html',
  styleUrls: [ './progressSpinner.component.scss' ],
  encapsulation: ViewEncapsulation.None,
})
export class ProgressSpinnerComponent {
  message: string;

  constructor() {}
}
progressSpinner.component.scss
.progress-spinner {
    color: white;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
  
.progress-spinner-backdrop {
    background-color: rgba(0, 0, 0, .30)!important;
}

.message {
    font-size: x-large;
    color: white;
    position: absolute;
    text-align: center;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

スピナーとテキストを持つだけのシンプルな構成。
スタイルシートはグローバルの styles.scss に書きたくなかったので切り出しているが、ViewEncapsulation.Noneを付けないと正しく読み込めなかった。
(雑だが、主題とは関係ないので、とりあえず割愛。)

サービス

コンポーネントを生成、管理するためのサービスを追加。
overlay の attach、detach などもこちらで管理する。

overlay を生成する時に、panelClass、backdropClass に先ほどのスタイルシートで定義したクラスをセットしている。

progressSpinner.service.ts
import { ComponentRef } from '@angular/core';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { Injectable } from '@angular/core';

import { ProgressSpinnerComponent } from './progressSpinner.component';

@Injectable({
  providedIn: 'root'
})
export class ProgressSpinnerService {

  overlayRef: OverlayRef;
  spinner: ComponentRef<ProgressSpinnerComponent>;

  constructor(
    private readonly overlay: Overlay,
  ) {}

  // show progress spinner
  public show(): void {
    const portal = new ComponentPortal(ProgressSpinnerComponent);

    this.overlayRef = this.overlay.create({
      width: '100%',
      height: '100%',
      hasBackdrop: true,
      panelClass: 'progress-spinner',
      backdropClass: 'progress-spinner-backdrop',
    });
    this.spinner = this.overlayRef.attach(portal);
  }

  public close(): void {
    this.overlayRef.detach();
    this.overlayRef.dispose();
  }

  public setMessage(message): void {
    this.spinner.instance.message = message;
  }
}

app.module.ts

他から呼び出せるようにするために、MatProgressSpinnerModule、ProgressSpinnerComponent の定義を app.module.ts に追加する。

app.module.ts
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ProgressSpinnerComponent } from './views/common/components/progressSpinner/progressSpinner.component';



@NgModule({
    declarations: [
        AppComponent,
        ProgressSpinnerComponent,
    ・
    ・
    ・
    imports: [
    ・
    ・
    ・
        MatProgressSpinnerModule,

呼び出し方

あとは任意のコンポーネントからサービスを import し、show → setMessage →・・・→ close としてやればOK。

import { ProgressSpinnerService } from '../../common/components/progressSpinner/progressSpinner.service';
    ・
    ・
    ・
  constructor(
    private spinner: ProgressSpinnerService,
  ) {}
    ・
    ・
    ・
  test() {
    try {
      // show spinner
      this.spinner.show();

      this.spinner.setMessage('ファイルアップロード中 10%');
    ・
    ・
    ・
      this.spinner.setMessage('ファイルアップロード中 20%');
    ・
    ・
    ・

    } catch (e) {
      alert(e.message);
    } finally {
      // stop spinner
      this.spinner.close();
    }
  }

※ とりあえずスピナーは1つしかない前提。
  複数ある場合、コンポーネントのインスタンスを返すようにするか、あるいはサービスを複数Injectするか。まあだいたい1つで事足りるでしょうけど。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?