ANGULARのサービス

前回の続きで、Angularのアプリケーションを作成していきます。

StockService の作成

Angular CLIを使用して、StockServiceを作成します。
これはコンポーネントからデータ取得ロジックを切り離す為です。

データ取得ロジックを別に設けることによって、モックからではなく、外部やローカルからデータを取得して使うことができます。
但し、この記事ではモックを使用します。

user@computer$ ng generate service stock

Angular

 

Stockデータの取得

StockServiceをStockComponentで利用できるようにします。
Angularのstock.service.tsファイルに次を記述しましょう。

import { Injectable } from ‘@angular/core’;
import { Stock } from ‘./stock’;
import { STOCKS } from ‘./mock-stocks’;
@Injectable({
  providedIn: ‘root’
})
export class StockService {
  getStocks(): Stock[]{
  return STOCKS;
  }
  constructor() { }
}

 

このプログラムでは、StockとモックのSTOCKSをインポートして、STOCKSをエクスポートしています。
プロバイダーのメタデータを@Injectableデコレーターに含めることによって、サービスの ルートインジェクタ でプロバイダーを登録します。
ルートアプリケーションインジェクターにサービスプロバイダーを追加すると、それはアプリケーション全体で使用することができます。

StocksComponentの更新

Angularのstocks.component.tsファイルを修正しましょう。

STOCKSのインポートを削除して、代わりにStockServiceをインポートしましょう。

import { StockService } from '../stock.service';

stocksプロパティの定義を、単純な宣言に置き換えます。

stocks: Stock[ ];

StockServiceの注入

stockServiceをコンストラクターに追加しましょう。
このパラメータはプライベートな stockServiceプロパティとして定義されると同時に、 StockServiceを注入すべき場所として認識されます。

constructor(private stockService: StockService) { }

getStocks() の追加

サービスからstockデータを取得するための関数を作成します。

getStocks(): void{
  this.stocks = this.stockService.getStocks();
  }

 

ngOnInitでの呼び出し

getStocks( )はコンストラクターでも呼び出すことはできますが、これは最適な方法ではありません。コンストラクターではプロパティ定義などの簡単な初期化のみを行い、それ以外は 何もするべきではありません

各インターフェースは、名前が ngで始まるインターフェース名である単一のフックメソッドを持っています。 たとえば、 OnInitインターフェースは ngOnInit( )という名前のフックメソッドを持っています。 Angularはコンポーネントの作成直後に呼び出します。

  ngOnInit() {
  this.getStocks();
  }

 

現在のブラウザの表示は、以前と一緒です。
Angular
stocks.component.tsファイルの全体コードは次の通りです。

import { Component, OnInit } from ‘@angular/core’;

import { Stock } from ‘../stock’;

//import { STOCKS } from ‘../mock-stocks’;

import { StockService } from ‘../stock.service’;

@Component({

  selector: ‘app-stocks’,

  templateUrl: ‘./stocks.component.html’,

  styleUrls: [‘./stocks.component.css’]

})

export class StocksComponent implements OnInit {

  selectedStock: Stock;

  stocks: Stock[];

  constructor(private stockService: StockService) { }

  ngOnInit() {

  this.getStocks();

  }

  onSelect(stock: Stock): void{

  this.selectedStock = stock;

  }

  getStocks(): void{

  this.stocks = this.stockService.getStocks();

  }

}

Observable データ

StockService.getStocks( )は同期的なメソッドなので、StockServiceは即座にStockデータを取得できます。
しかし、実際のアプリケーションでは機能しません。
現在は、モックからデータを得ているからです。

StockService.getStocks( )は何らかの非同期処理を実装する必要があります。
非同期処理の実装には、コールバック関数、Promiseまたは Observableを使用できます。

ここでは、StockService.getStocks( )は Observableを返します。 なぜなら、後にヒーローデータの取得で利用する Angular の HttpClient.get( )メソッドが Observableを返すからです。

Observable StockService

Observableおよび of を RxJS からインポートします。
RxJSの of( )関数を使ってサーバーからのデータの取得をシミュレートします。

getStocksメソッドを Observable形式で書き直しましょう。
Angularのstock.service.tsファイルに次を記述しましょう。

import { Injectable } from ‘@angular/core’;

import { Stock } from ‘./stock’;

import { STOCKS } from ‘./mock-stocks’;

import { Observable, of } from ‘rxjs’;

@Injectable({

  providedIn: ‘root’

})

export class StockService {

  getStocks(): Observable<Stock[]>{

  return of(STOCKS);

  }

  constructor() { }

}

StocksComponent の Subscribe

StockService.getStocks メソッドは Stock[ ]を返していましたが、 現在の返り値は Observable<Stock[ ]>です。

そのため、それらの違いを修正する必要があるでしょう。

Angularのstocks.component.tsファイルを修正しましょう。

 getStocks(): void{

  this.stockService.getStocks()

  .subscribe(stocks => this.stocks = stocks);

  }

メッセージの表示

この節では次のことを行います。

  • メッセージを表示するための MessagesComponent を画面下部に追加する

  • 表示するメッセージを送信するために、アプリケーション全体で注入可能な MessageServiceを作成する

  • StockService に MessageService を注入する

MessagesComponent の作成

Angular CLI を使い MessagesComponentを作成します。

user@computer$ ng generate component messages

Angularのapp.component.htmlに追加します。

<h1>{{title}}</h1>
<app-stocks></app-stocks>
<app-messages></app-messages>

MessageService の作成

Angular CLI を使い、MessageServiceを追加します。

user@computer$ ng generate service message

 

Angularのmessage.service.tsファイルを開き、次のように修正します。

import { Injectable } from ‘@angular/core’;
@Injectable({
  providedIn: ‘root’
})
export class MessageService {
  messages: string[] = [];
  add(message: string){
    this.messages.push(message);
  }
  clear(){
  this.messages = [];
  }
}

 

add( )メソッドは新たなメッセージを messagesへ追加し、clear( )メソッドは messagesの値を初期化します。

StockServiceへの注入

stock.service.tsファイルに記述します。

import { Injectable } from ‘@angular/core’;
import { Stock } from ‘./stock’;
import { STOCKS } from ‘./mock-stocks’;
import { Observable, of } from ‘rxjs’;
import { MessageService } from ‘./message.service’;
@Injectable({
  providedIn: ‘root’
})
export class StockService {
  getStocks(): Observable<Stock[]>{
    // TODO: send the message _after_ fetching the stocks
    this.messageService.add(‘StockService: fetched stocks’);
  return of(STOCKS);
  }
  constructor(private messageService: MessageService) { }
}

 

StockServiceからのメッセージを表示する

messages.component.tsに記述します。

import { Component, OnInit } from '@angular/core';
import { MessageService } from '../message.service';

@Component({
selector: ‘app-messages’,
templateUrl: ‘./messages.component.html’,
styleUrls: [‘./messages.component.css’]
})
export class MessagesComponent implements OnInit {

constructor(public messageService: MessageService) { }

ngOnInit() {
}

}

 

MessageService へバインドする

Angular CLI によって生成されたmessages.component.htmlを開いて、記述しましょう。

<div *ngIf=”messageService.messages.length”>
<h2>Messages</h2>
<button class=”clear”
(click)=”messageService.clear()”>clear</button>button>
<div *ngFor=’let message of messageService.messages’> {{message}} </div>
</div>

 

このテンプレートは、コンポーネント内の messageService と直接紐付きます。

  • *ngIfは、表示するメッセージが存在する場合のみメッセージエリアを表示します
  • *ngFor は、<div> 要素をくり返してメッセージリストを表示します
  • Angular の イベントバインディング は、ボタンのクリックイベントと MessageService.clear() を紐付けます

スタイルシートを適用します。

messages.component.cssを記述します。

  1. /* MessagesComponent’s private CSS styles */
  2. h2 {
  3. color: red;
  4. fontfamily: Arial, Helvetica, sansserif;
  5. fontweight: lighter;
  6. }
  7. body {
  8. margin: 2em;
  9. }
  10. body, input[text], button {
  11. color: crimson;
  12. fontfamily: Cambria, Georgia;
  13. }
  14.  
  15. button.clear {
  16. fontfamily: Arial;
  17. backgroundcolor: #eee;
  18. border: none;
  19. padding: 5px 10px;
  20. borderradius: 4px;
  21. cursor: pointer;
  22. cursor: hand;
  23. }
  24. button:hover {
  25. backgroundcolor: #cfd8dc;
  26. }
  27. button:disabled {
  28. backgroundcolor: #eee;
  29. color: #aaa;
  30. cursor: auto;
  31. }
  32. button.clear {
  33. color: #888;
  34. marginbottom: 12px;
  35. }

 

ブラウザで見ると、次のように変わりました。
Angular
ここまでで、次を行いました。

データ取得ロジックを切り離すために、StockServiceを作成しました。
stock.service.tsに記述しました。
stocks.component.tsを修正しました。
stockServiceをコンストラクターに追加しました。
getStocks( ) 関数を作成しました。
ngOnInit( )に追記しました。
import { Observable, of } from ‘rxjs’;をしました。
Subscribeを修正しました。
MessagesComponentを作成しました。
MessageServiceを作成しました。
stock.service.tsに変更を追記しました。
messages.component.tsに記述しました。
messages.component.htmlを記述しました。
messages.component.cssを記述しました。









佐々木俊尚のネット未来地図レポート

視力回復&脳活性プログラム「アイアップ!」

東大記憶法 ~記憶力90日向上プロジェクト~(記憶法・遠隔セミナー)

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください