ふわりAngular

このサイトはAngularで作られています。

Angular初心者なので玄人向けの情報はありません。

初心者の方、理解レベルが同じくらいの方のお役に立てれば幸いです。

2016/12/28

サービスを使おう


前回、 TODOリストを作ってみようでは簡単なアプリケーションを作成しました。

今回はロジック部分をDI化(Dependency Injection)するため、サービスクラスを作ってみます。

サービスを作ることで、ほかのコンポーネントでも同じ処理が使えるようになりますし、何よりユニットテストが楽になります。


次の流れでサービスを作成します。

  • データモデルクラスを作成する
  • サービスクラスを @Injectable()で作成する
  • モジュールにて利用宣言(providers)をする
  • コンポーネントにて利用宣言(Constructor Injection)

データモデルクラスを ng generate classで作成する


サービスとは直接関係ありませんが、データモデルクラスを先に作っておきます。

ng generate class [クラス名]を実行してください

$ ng generate class todo
installing class
  create src\app\todo.ts

クラスファイルが自動生成されたら、app.component.ts から Todoクラスを移植します。

todo.ts

  1. export class Todo
  2. title: string;
  3. desc: string;

サービスクラスを @Injectable()で作成する


サービスクラスの作成は、 ng generate service [サービス名]で行います。

$ ng generate service todo
installing service
  create src\app\todo.service.spec.ts
  create src\app\todo.service.ts
  WARNING Service is generated but not provided, it must be provided to be used

コンソールに「サービスを作ったけど利用宣言されてないよ。使いたかったら利用宣言してね」と警告が出ていますね。

こちらは後ほどモジュールの修正を行いますので、まずはサービスクラスの移植を行います。

todo.service.ts

  1. import Injectable from '@angular/core';
  2. import Todo from './todo';
  3.  
  4. @Injectable()
  5. export class TodoService
  6.  
  7. private todos: Todo[] = [];
  8.  
  9. constructor()
  10.  
  11. public get list(): Todo[]
  12. return this.todos;
  13. public add(todo: Todo): void
  14. this.todos.push(todo);
  15. public delete(index: number): void
  16. this.todos.splice(index, 1);

モジュールにて利用宣言(providers)をする


先ほどコンソールに警告が出ていたように、作成したサービスを利用するための宣言をする必要があります。

app.module.ts の providers にサービスクラスを定義します。

app.module.ts

  1. import BrowserModule from '@angular/platform-browser';
  2. import NgModule from '@angular/core';
  3. import FormsModule from '@angular/forms';
  4. import HttpModule from '@angular/http';
  5.  
  6. import AppComponent from './app.component';
  7. import TodoService from './todo.service';
  8.  
  9. @NgModule({
  10. declarations: [
  11. AppComponent
  12. ],
  13. imports: [
  14. BrowserModule,
  15. FormsModule,
  16. HttpModule
  17. ],
  18. providers: [TodoService],
  19. bootstrap: [AppComponent]
  20. })
  21. export class AppModule

コンポーネントにて利用宣言(Constructor Injection)


最後に app.component.ts からサービスを利用するよう修正しましょう。

ポイントは、コンストラクタにて宣言する(Constructor Injection)ことです。

app.component.ts

  1. import Component from '@angular/core';
  2. import Todo from './todo';
  3. import TodoService from './todo.service';
  4.  
  5. @Component({
  6. selector: 'app-root',
  7. templateUrl: './app.component.html',
  8. styleUrls: ['./app.component.css']
  9. })
  10. export class AppComponent
  11.  
  12. constructor(
  13. private todoService: TodoService
  14. )
  15.  
  16. private todo: Todo;
  17. private todos: Todo[];
  18. ngOnInit(): void
  19. this.todo = new Todo;
  20. this.todos = this.todoService.list;
  21. public onSubmit(): void
  22. this.todoService.add(this.todo);
  23. this.todo = new Todo;
  24. public onDelete(index: number): void
  25. this.todoService.delete(index);

以上で移植が完了です。


動作を確認する。


コードを保存して、 ng serveで動かしてみましょう。

動作自体はサービスを作る前と変わらないことが確認できるかと思います。

動作は変わりませんが、サービスを作ることで画面とビジネスロジックの分離ができました。

例えば、APIを呼ぶ処理やローカルストレージを利用する処理など、サービスに書くことになるでしょう。

ソースコードはGitHubに登録しておきますので参考にしてください。

c5apple/angular2-todos/issues/1