Angularでは、アプリケーションのロジックやデータ管理をサービス(Service)に切り出し、効率的に再利用・共有できます。
本章では、サービスの作成から、依存性注入(Dependency Injection, 略称DI)の仕組み、さらに複数コンポーネント間での状態共有までを詳しく解説します。

1. サービスの作成と登録
サービスとは、コンポーネントから独立したビジネスロジックの塊です。データの取得、状態管理、共通処理などを担います。
■ サービス作成コマンド
Angular CLIを使えば、簡単にサービスを作成できます。
ng generate service user
これにより以下のファイルが生成されます。
user.service.ts
(サービス本体)user.service.spec.ts
(テストファイル)
サービスはデフォルトで、アプリ全体(rootスコープ)に登録されます。
■ シンプルなサービス例
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class UserService {
private userName = 'ゲスト';
getUserName(): string {
return this.userName;
}
setUserName(name: string) {
this.userName = name;
}
}
@Injectable()
デコレーターを付与し、サービスクラスをAngularのDIシステムに登録します。
2. DI(依存性注入)の仕組みと呼び出し方
依存性注入(Dependency Injection)とは、必要な依存オブジェクト(ここではサービス)を、コンポーネント側で自ら生成せずに、外部から「注入」してもらう仕組みです。
■ コンストラクタでサービスを注入する
import { Component } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-user',
template: '<p>ユーザー名: {{ userName }}</p>'
})
export class UserComponent {
userName = '';
constructor(private userService: UserService) {
}
ngOnInit() {
this.userName = this.userService.getUserName();
}
}
- constructor(private userService: UserService):ここでDIされる
- ngOnInit():コンポーネント初期化時にサービスメソッドを呼び出し
このようにDIを使えば、テストしやすく、保守性の高いコードが書けます。
3. 複数コンポーネント間での状態共有
サービスを使う最大の利点のひとつが、複数のコンポーネント間でデータや状態を共有できることです。
■ 状態共有の流れ
- サービスでデータを保持
- コンポーネントAがデータを更新
- コンポーネントBが同じサービスからデータを取得
■ 例:名前の更新と表示
// name.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class NameService {
private name = '初期名';
getName(): string {
return this.name;
}
updateName(newName: string) {
this.name = newName;
}
}
// name-input.component.ts
import { Component } from '@angular/core';
import { NameService } from '../name.service';
@Component({
selector: 'app-name-input',
template: ` <input [(ngModel)]="inputName" /> <button (click)="changeName()">名前変更</button&> `
})
export class NameInputComponent {
inputName = '';
constructor(private nameService: NameService) {
}
changeName() {
this.nameService.updateName(this.inputName);
}
}
// name-display.component.ts
import { Component } from '@angular/core';
import { NameService } from '../name.service';
@Component({
selector: 'app-name-display',
template: '<p>現在の名前: {{ nameService.getName() }}</p>'
})
export class NameDisplayComponent {
constructor(public nameService: NameService) {
}
}
このように、サービスを通じて別々のコンポーネント間でデータの一貫性を保てます。
まとめ
Angularのサービスと依存性注入(DI)は、コードの再利用性を高め、状態管理やロジックの分離を強力にサポートします。
複数コンポーネント間でのデータ共有にも不可欠な技術なので、早い段階でマスターしておきましょう。