Angularでサービスを作ろう
2018/08/31
はじめに
Angularとは?という方はこの記事をご覧ください。
前提
angular-cliインストール済
そもそもサービスって?
ビジネスロジックを切り出したものです。
各コンポーネントやサービスで依存性注入(DI)して利用することができます。
jQueryだとajaxで情報を取得してコールバック内でDOM操作して・・というプログラムになりがちです。
同じ情報を取得する必要があれば、関数として切り出して(最悪コピペして)・・・とやっていくと、どの関数がどこで呼び出されているか分からなくなり、
あっという間においしい(くない)スパゲッティが完成してしまいます・・・(;_;)
Angularではサービスとして切り出したものをDIして利用するので、
見通しの良さを保ちながらロジックと画面を分離することができるんです!
Typescriptなら呼び出せない関数を呼び出した場合はコンパイルエラーになるので、実装時も安心です!
というわけで、さっそくサービスを作っていきましょう。
今回は話を簡単にするために
- サービスに処理を定義して
- コンポーネントからサービスの処理を呼び出して
- 画面に表示する
までとします。
サービスの雛形を作る
> ng new testApp
> cd path/to/testApp
> ng g service test -m app
installing service
create src\app\test.service.spec.ts
create src\app\test.service.ts
update src\app\app.module.ts
ポイントになるのは最後のコマンドです。
たった1つのコマンドでサービスの雛形が出来ました。(angular-cliすごい)
本来であれば生成されたファイルを「services」フォルダに移して、DIのパスを修正して・・等をするのですが
今回はサンプルということでフォルダ構成はこのままで進めます。
-mはサービスをDIするモジュールを指定して、DIの記載をangular-cliにやってもらっています。
ダミーデータを作る
データを取得したいのですが、肝心のデータがありません。( ´・ω・`)
適当なjsonファイルを準備しましょう。
作ったファイルはassetsフォルダに入れておきます。
sample.json
[
{ "id": 1, "name": "Sato" },
{ "id": 2, "name": "Suzuki" },
{ "id": 3, "name": "Takahashi" }
]
jsonファイルの内容を取得して返す
app.module.ts
Web APIを叩くことを想定して、HttpModuleをDIします。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { TestService } from './test.service';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpModule
],
providers: [TestService],
bootstrap: [AppComponent]
})
export class AppModule { }
test.service.ts
これがサービスの本体となります。
fetchの中で色々やっていますが、1つ1つは簡単です。
- ダミーデータをGETで取得して
- レスポンスボディ(JSON)をパースして
- Promiseに変換して返す
Observableは勉強中なので、Promiseでやります(汗)
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/Rx';
@Injectable()
export class TestService {
constructor(private http: Http) { }
fetch() {
return this.http
.get('../assets/sample.json')
.map((resp) => resp.json())
.toPromise();
}
}
app.component.ts
定義したサービスの処理を呼び出しましょう。
TestServiceをインポートしてコンストラクタ内でDIします。
ngOnInitの中でサービスを呼び出して、結果をlistに格納します。
ngOnInitはOnInitインターフェースの実装で、コンポーネントの初期処理を定義することができます。
import { Component, OnInit } from '@angular/core';
import { TestService } from './test.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
list = [];
constructor(private testService: TestService) { }
ngOnInit() {
this.testService
.fetch()
.then((resp) => {
this.list = resp;
});
}
}
app.component.html
<table class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of list">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
動作確認
> ng serve
// => localhost:4200にアクセス
無事コンポーネントからサービスを呼び出して、画面に表示できました!!
もし同じ情報を他のコンポーネントにも表示する必要があれば同じようにDIして呼び出すだけです。
スタイルにはSpectre.cssを使いました。シンプルでキレイなのでお気に入りです。
次回
WebアプリではURLが○○ならこれを表示して、こういう処理をして、存在しないURLなら404メッセージを出して・・等の処理をすると思います。
これを実現するのがAngularのルーティングです!щ(゚Д゚щ)
それについてはまた後日!!