この記事ではAngularの『サービス』について、以下の内容をサンプルコード用いてわかりやすく解説します。
- Angularの「サービス」とは
- Angularの「サービス」の使い方
@Injectable
デコレーター内にprovidedIn: 'root'
を記述しない場合のサービスの使い方
Angularの「サービス」とは
Angularにはサービスという便利な機能があります。
Angularのコンポーネントは見た目(テンプレート)の表示に専念し、ビジネスロジック(データの取得、データの変更、データの計算などをする処理)はサービスに任せるのが一般的です。
例えば、コンポーネント内で外部のWeb APIからデータを取得したり、複雑なデータを整形したりするのは好ましくありません。これらの処理はサービスに任せます。
コンポーネントにあるビジネスロジックをサービスに切り出すことで、コンポーネントは見た目(テンプレート)の表示に専念することができるようになります。
サービスの使用例としては以下のようなものが考えられます。
サービスの使用例
- 商品(例えば本など)の情報を取得するサービス
- BookService
- チケットの予約を行うサービス
- BookingService
この記事では、一例として、シンプルに「Hello Angular!」のみを出力するサービス(MessageService)の作成方法や使い方を説明します。
Angularの「サービス」の使い方
Angularの「サービス」を使用する手順を以下に示します。
Angularの「サービス」を使用する手順
- サービスを作成する
- サービスを編集する
- サービスをコンポーネントに注入する
上記の手順について、順番に説明します。
サービスを作成する
まず、サービスの雛形を作成します。
カレントディレクトリ(現在作業しているディレクトリ)がプロジェクトのルートディレクトリであることを確認してください。その後、Angular CLIが提供している「ng generate service
コマンド」を実行すると、サービスの雛形を作成することができます。以下のコマンドを実行してください。
ng generate service [サービス名]
# この記事では、MessageServiceというサービスを作成するので、以下のコマンドを実行しています。
ng generate service message
このコマンドを実行すると、「src/app」ディレクトリに「サービスファイル(message.service.ts)」と「サービスのユニットテストのファイル(message.service.spec.ts)」が作成されます。
作成された「サービスファイル(message.service.ts)」は以下の内容になっています。
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MessageService {
constructor() { }
}
上記のプログラムではAngularのInjectable
がインポートされています。
また、クラス定義(export class MessageService
)の前に@Injectable
デコレーターを付与することで、MessageService
はサービスクラスになります。これは、AngularがこのMessageService
サービスクラスを他のサービスクラス・コンポーネント・モジュールに注入(inject)可能であることを示しています。
また、@Injectable
デコレーター内のprovidedIn: 'root'
はMessageService
サービスクラスがアプリケーションのルートインジェクターに登録されていることを示しており、このMessageService
サービスクラスがアプリケーションのどこからでも利用可能なことを示しています。
「サービスのユニットテストのファイル(message.service.spec.ts)」は使わないので、削除してもOKです。
サービスを編集する
次に自動生成された「サービスファイル(message.service.ts)」を編集します。以下のプログラムは、今回作成したMessageService
サービスクラスの一例です。
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MessageService {
message(): string {
return 'Hello Angular!';
}
}
サービスとして提供するべきメソッドを入力しています。上記のプログラムでは、Hello Angular!
を返すmessage
メソッドを定義しています。
今回は一例として、簡単なメソッドを書きましたが、一般的には外部サービスに問い合わせた結果などを取得するメソッドを記述します。
サービスをコンポーネントに注入する
次に、MessageService
サービスクラスをコンポーネントに注入する必要があります。以下のプログラムは、今回作成したAppComponent
コンポーネントクラスの一例です。
import { Component } from '@angular/core';
import { MessageService } from './message.service';
@Component({
selector: 'app-root',
template: `{{receiveMessage}}`,
})
export class AppComponent {
receiveMessage: string | undefined;
constructor(private messageService: MessageService) { }
ngOnInit() {
this.receiveMessage = this.messageService.message();
}
}
サービスをコンポーネントに注入する手順を以下に示します。
サービスをコンポーネントに注入する手順
MessageService
をインポートする- コンストラクタにサービス型の引数を追加する
上記の手順について、順番に説明します。
MessageServiceをインポートする
import { MessageService } from './message.service';
AppComponent
コンポーネントクラスでMessageService
サービスクラスを使用するためには、上記のプログラムのようにMessageService
をインポートします。
コンストラクタにサービス型の引数を追加する
constructor(private messageService: MessageService) { }
次に、コンストラクタにサービス型(ここではMessageService
)の引数を追加します。
上記のプログラムでは、MessageService
サービスクラスのインスタンスをmessageService
プロパティとして宣言し、同時にコンストラクタ内で初期化しています。これにより、このコンストラクタを持つクラス(ここでは、AppComponent
)内において、this.message.~
の形式でコンポーネントのどこからでもアクセスできるようになります。
private
アクセス修飾子は、その後に続くプロパティやメソッドがそのクラス内でのみアクセス可能であることを示しています。つまり、上記のプログラムでは、messageService
プロパティはAppComponent
コンポーネントクラス内でのみアクセス可能であることを示しています。
Angularのテンプレートからもmessageservice
プロパティにアクセスしたい場合には、public
アクセス修飾子にします。public
アクセス修飾子は、その後に続くプロパティやメソッドがどこからでもアクセス可能であることを示しています。
以上で準備が完了です。では実際にアプリを実行してみましょう。実行結果は以下のようになります。
プログラムの実行結果
【補足】下記のプログラムはどちらも同じ
TypeScriptのパラメータプロパティ(Parameter properties)を利用すると、クラスのコンストラクタ内で直接プロパティを宣言し、初期化することができます。これにより、コードが簡潔になり、その結果、可読性が向上します。
以下の例では、MessageService
サービスクラスのインスタンスをmessageService
プロパティとして宣言し、同時にコンストラクタ内で初期化しています。
constructor(private messageService: MessageService) { }
これは以下のようなコードと同じ意味を持ちます。
private messageService: MessageService;
constructor(messageService: MessageService){
this.messageService = messageService;
}
@Injectableデコレーター内に「providedIn: 'root'」を記述しない場合
@Injectableデコレーター内にprovidedIn: 'root'
を記述すると、サービスクラスがアプリケーションのどこからでも利用可能になります。
このprovidedIn: 'root'
の指定を無くすと、モジュールやコンポーネントの中だけに利用範囲を限定させることができます。
モジュールの中のみでサービスを利用する場合
MessageServiceサービスクラスとAppModuleモジュールを以下のように記述します。
MessageServiceサービスクラス
import { Injectable } from '@angular/core';
@Injectable() //「providedIn: 'root'」を削除
export class MessageService {
message(): string {
return 'Hello Angular!';
}
}
上記のプログラムに示すように、@Injectable
デコレーター内にあるprovidedIn: 'root'
を削除します。
AppModuleモジュール
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { MessageService } from './message.service'; //MessageServiceサービスクラスをインポート
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [MessageService], //@NgmoduleデコレーターのprovidersパラメータにMessageServiceサービスクラスを追加
bootstrap: [AppComponent]
})
export class AppModule { }
上記のプログラムに示すように、MessageService
サービスクラスをAppModule
モジュールに登録します。
MessageService
サービスクラスをAppModule
モジュールに登録するには以下の手順で行います。
サービスクラスをAppModuleモジュールに登録する手順
- サービスクラスをインポートする
Ngmodule
デコレーターのproviders
パラメータにサービスクラスを追加する
上記の手順について、順番に説明します。
サービスクラスをインポートする
import { MessageService } from './message.service';
まず、上記に示すようにMessageService
サービスクラスをインポートします。
Ngmoduleデコレーターのprovidersパラメータにサービスクラスを追加する
providers: [MessageService],
次に、@Ngmodule
デコレーターのproviders
パラメータにMessageService
サービスクラスを追加します。
このように記述することで、モジュール(ここでは、AppModule)の全体でサービスを利用できるようになります。
コンポーネントの中のみでサービスを利用する場合
MessageServiceサービスクラスとAppComponentコンポーネントクラスを以下のように記述します。
MessageServiceサービスクラス
import { Injectable } from '@angular/core';
@Injectable() //「providedIn: 'root'」を削除
export class MessageService {
message(): string {
return 'Hello Angular!';
}
}
上記のプログラムに示すように、@Injectable
デコレーター内にあるprovidedIn: 'root'
を削除します。
AppComponentコンポーネントクラス
import { Component } from '@angular/core';
import { MessageService } from './message.service';
@Component({
selector: 'app-root',
template: `{{receiveMessage}}`,
providers: [MessageService], //@ComponentデコレーターのprovidersパラメータにMessageServiceサービスクラスを追加
})
export class AppComponent {
receiveMessage: string | undefined;
constructor(private messageService: MessageService) { }
ngOnInit() {
this.receiveMessage = this.messageService.message();
}
}
@Component
デコレーターのproviders
パラメータにMessageService
サービスクラスを追加します。
providers: [MessageService],
この場合、サービスは現在のコンポーネント(ここでは、AppComponent)と子コンポーネントのみで利用できるようになります。
本記事のまとめ
この記事ではAngularの『サービス』について、以下の内容を説明しました。
- Angularの「サービス」とは
- Angularの「サービス」の使い方
@Injectable
デコレーター内にprovidedIn: 'root'
を記述しない場合のサービスの使い方
お読み頂きありがとうございました。