Angular Material Progress spinner 導入

## Progress spinner とは

- 画面処理中を表すくるくる回るやつです。  
![image](https://user-images.githubusercontent.com/38905609/174576473-cb32bcec-94d0-4788-8e53-4e2f9329de99.png)
![image](https://user-images.githubusercontent.com/38905609/174576198-b0bb54a8-0ffc-4d67-8414-3626f82d2708.png)

## この記事の目的

- Angular Material のProgress spinnerを組み込みます。

## 👇これより先は下記記事の内容を前提とします

- [Angular Material 標準コンポーネント構成の作成](https://docusaurus.plant11.com/angular/base_components)

## Progress spinner の組み込み

### サービスの作成

```sh
ng generate service loading
```

`loading.service.ts`

```ts:loading.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

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

  subject = new Subject<string>();

  constructor() { }

  setLoading(strMessage: string): void {
    this.subject.next(strMessage);
  }

  unsetLoading(): void {
    this.subject.next('');
  }

}
```

### Component追加

```sh
ng generate component spinner-sample
```

## Material ProgressSpinner 導入

`app.module.ts`

```ts:app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SpinnerSampleComponent } from './spinner-sample/spinner-sample.component';

import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';     // add
import {MatButtonModule} from '@angular/material/button';                        // add

@NgModule({
  declarations: [
    AppComponent,
    SpinnerSampleComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatProgressSpinnerModule,   // add
    MatButtonModule,            // add
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

## ComponentとSpinnerの組み込み

`app.component.ts`

```ts:app.component.ts
import { Component,OnInit } from '@angular/core';

import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { LoadingService } from './loading.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{

  loading$: Observable<string> = this.loadingService.subject.asObservable();
  strMsg:string="";

  constructor(private loadingService: LoadingService) { }

  title = 'material.angular.github';

  ngOnInit(): void {
    this.loading$.subscribe(
      (value: string) => { this.strMsg=value; }
    );
  }
}
```

`app.component.css`

```css:app.component.css
.loading {
  display: table;
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background-color: #fff;
  opacity: 0.8;
  z-index: 1;
}

.loading-inner {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

mat-spinner {
  margin: 0 auto;
}
```

`app.component.html`

```html:app.component.html
<div *ngIf="strMsg!==''" class="loading">
  <div class="loading-inner">
    <mat-spinner></mat-spinner>
    {{strMsg}}
  </div>
</div>

<app-spinner-sample></app-spinner-sample>
```

`spinner-sample.component.ts`

```ts:spinner-sample.component.ts
import { Component, OnInit } from '@angular/core';

import { LoadingService } from '../loading.service';

@Component({
  selector: 'app-spinner-sample',
  templateUrl: './spinner-sample.component.html',
  styleUrls: ['./spinner-sample.component.css']
})
export class SpinnerSampleComponent implements OnInit {

  constructor(private loadingService: LoadingService) { }

  ngOnInit(): void {
  }

  button_click(){
    this.showLoading("loading");
    setTimeout(() => {
      this.hideLoading();
    }, 2000);
  }

  showLoading(strMessage: string):void {
    this.loadingService.setLoading(strMessage);
  }

  hideLoading():void {
    this.loadingService.unsetLoading();
  }
}
```

`spinner-sample.component.html`

```html:spinner-sample.component.html
<p>spinner-sample works!</p>
<button mat-stroked-button (click)="button_click()">Spinner!!!</button>
```

## 表示確認

```sh
ng serve --open
```

![image](https://user-images.githubusercontent.com/38905609/174576473-cb32bcec-94d0-4788-8e53-4e2f9329de99.png)
![image](https://user-images.githubusercontent.com/38905609/174576198-b0bb54a8-0ffc-4d67-8414-3626f82d2708.png)

## 👇前提記事

- [Angular Material 標準コンポーネント構成の作成](https://docusaurus.plant11.com/angular/base_components)

## 👇関連記事

- [Angular Material datepicker 導入](https://docusaurus.plant11.com/angular/datepicker)
- [Angular Material 動的Tree 導入](https://docusaurus.plant11.com/angular/dynamic_tree)
- [StackBlitzの導入からGitHub同期まで](https://docusaurus.plant11.com/tips/StackBlitz)

## 👇GitHubはこちら

- <https://github.com/jun-knd/material.angular.github/tree/progress-spinner>
[![image](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/jun-knd/material.angular.github/tree/progress-spinner)

## 👇参考URL

- [Angular Materialで処理中の待ち受け画面](https://nanbu.marune205.net/2021/12/angular-material-waiting.html?m=1)