1
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 5 years have passed since last update.

Angularヒーローチュートリアル5

Posted at

サービス

サービスとは、データを取得しコンポーネントに提供する部分です。

サービスの作成

ターミナル
$ cd src/app
$ ng generate service hero

hero.service.tshero.service.spec.tsが生成されます。
hero.service.tsでデータの処理を行っていきます。

データの取得

自動で生成されたコードに少し加えます。

hero.service.ts
import { Injectable } from '@angular/core';
//以下2行でヒーロー情報の型とデータをインポート
import {Hero} from './hero';
import {HEROES} from './mock-heroes';

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

  constructor() { }

  getHeroes(): Hero[]{ //ヒーローのデータを返す関数を定義
    return HEROES;
  }
}

heroコンポーネントの修正

heroコンポーネントでデータをインポートしていましたが、サービスから提供してもらうのでコンポーネントではデータの代わりにサービスをインポートします。

hero.component.ts
import { Component, OnInit } from '@angular/core';
import {Hero} from '../hero';
import {HeroService} from '../hero.service';//サービスをインポート

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

  heroes: Hero[];//宣言を変更
  selectedHero: Hero;

  //サービスをインポートしたらコンストラクタで宣言する
  constructor(private heroService: HeroService) { }

  ngOnInit() {//ここで関数を呼び出す
    this.getHeroes();//下で作る関数を呼び出す
  }

  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }

  getHeroes(): void{//取得したデータを代入する関数を定義
    this.heroes = this.heroService.getHeroes();
  }
}

色々変更していますが、サービスからデータを取得してコンポーネントで使用できるようにしています。

Observableの利用

このままではサーバーからデータを取得するとき動作しません。
そんな時でも動作するようにtsファイルを変更します。(非同期的手法)

hero.service.ts
import { Injectable } from '@angular/core';
import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {Observable, of} from 'rxjs'//ここを追加

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

  constructor() { }

  getHeroes(): Observable<Hero[]>{//ここを変更
    return of(HEROES);
  }
}

関数の戻り値とその型を変更しました。こうすることで、サーバーからデータを取得する際に時間がかかっても待ってくれます。ここで型を変更したのでhero.component.tsも変更する必要があります。

hero.component.ts
  getHeroes(): void{//変更した関数
    this.heroService.getHeroes().subscribe(
      heroes => this.heroes = heroes
    );
  }

もう正直訳わからないですね。今はおまじない程度でいいと思います。これで今まで通り動作します。

メッセージの表示

データを取得できたときメッセージを出力するようにします。

今回メッセージを出力させるmessageコンポーネントに加えて、「データ取得との紐付け・メッセージを記憶・コンポーネントへ渡す」の役割をはたすmessageサービスの二つを作成します。

ターミナル
$ cd src/app
$ ng generate component message
$ ng generate service message

次に出力する場所をhtmlで一番下に設定します。

app.component.html
<h1>{{title}}</h1>
<app-heroes></app-heroes>
<app-message></app-message>

サービスでメッセージを追加、消去する関数を定義します。

message.service.ts
import { Injectable } from '@angular/core';

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

  messages: string[] = [];//メッセージを代入する変数を定義

  constructor() { }

  add(message:string){//引数のmessageをmessagesにpushで代入
    this.messages.push(message);
  }

  clear(){//messagesの中身を空にする
    this.messages = [];
  }
}

ここで作成された関数をhero.service.tsで使用します。

hero.service.ts
import { Injectable } from '@angular/core';
import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {Observable, of} from 'rxjs';
import {MessageService} from './message.service';//サービスをインポート

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

  //サービスをインポートしたのでコンストラクタでサービスを宣言
  constructor(private messageService: MessageService) { }

  getHeroes(): Observable<Hero[]>{
    //データを取得したらメッセージを代入
    this.messageService.add('HeroService: fetched heroes');
    return of(HEROES);
  }
}

ここで代入されたmessagesをmessageコンポーネントに渡します。

message.component.ts
import { Component, OnInit } from '@angular/core';
import { MessageService } from '../message.service';//サービスをインポート

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

  //サービスをインポートしたのでコンストラクタでサービスを宣言
  constructor(public messageService: MessageService) { }

  ngOnInit() {
  }

}

今回はコントラクタでサービスの宣言をpublicで行ったので、messageコンポーネント内でサービスが使用できます。それを利用してHTMLを書いていきます。

message.component.html
<div *ngIf="messageService.messages.length">

    <h2>Messages</h2>
    <button class="clear"
            (click)="messageService.clear()">clear</button>
    <div *ngFor='let message of messageService.messages'> {{message}} </div>
  
</div>
スクリーンショット 2020-02-04 20.51.58.png このようにメッセージが出力されるようになりました。
1
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
1
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?