- はじめに
- 事前学習
- 環境構築
- 新規アプリケーションの作成
- アプリケーションのビルド・起動
- 生成されたAppコンポーネントの確認と編集
- コンポーネントの作成
- UserListコンポーネントの表示
- ユーザ一覧の表示
- REST APIでユーザ一覧を取得
- さいごに
はじめに
近いうちにAngularを使いそうなので学習の過程をメモしていきます。
今回は環境構築から簡単なコンポーネントの作成、REST APIアクセスまでを実践していきます。
事前学習
とりあえずYouTubeで angular
と検索し、トップに出てきた以下の動画で学習しました。
TypeScriptの基本からAngularの仕組みについてわかりやすく説明されているので、英語が苦でなければおすすめします。
本エントリで実施する範囲はほぼこの動画でカバーできると思いますが、APIアクセス周りについては以下の記事を参考にしました。
- Building and Consuming a REST API with Angular 10/9: Sending GET Requests with HttpClient and Services by Example – Shabang.dev
- Angular 10 HttpClient | Techiediaries
環境構築
Node.jsのインストール
実行環境としてNodeが必要なのでインストールします。
バージョンは2020/8/10時点で最新の v14.7.0
を用意しました。
❯ nvm install v14.7.0
Angularのインストール
npmで @angular/cli
をインストールします。
❯ npm install -g @angular/cli npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated har-validator@5.1.5: this library is no longer supported /Users/hiroki_sawano/.nvm/versions/node/v14.7.0/bin/ng -> /Users/hiroki_sawano/.nvm/versions/node/v14.7.0/lib/node_modules/@angular/cli/bin/ng > @angular/cli@10.0.5 postinstall /Users/hiroki_sawano/.nvm/versions/node/v14.7.0/lib/node_modules/@angular/cli > node ./bin/postinstall/script.js ? Would you like to share anonymous usage data with the Angular Team at Google under Google’s Privacy Policy at https://policies.google.com/privacy? For more details and how to change this setting, see http://angular.io/analytics. No + @angular/cli@10.0.5 added 280 packages from 206 contributors in 53.464s
バージョンは 10.0.5
です。
❯ ng --version _ _ ____ _ ___ / \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _| / △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | | / ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | | /_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___| |___/ Angular CLI: 10.0.5 Node: 14.7.0 OS: darwin x64 Angular: ... Ivy Workspace: Package Version ------------------------------------------------------ @angular-devkit/architect 0.1000.5 @angular-devkit/core 10.0.5 @angular-devkit/schematics 10.0.5 @schematics/angular 10.0.5 @schematics/update 0.1000.5 rxjs 6.5.5
新規アプリケーションの作成
ng newで新規アプリを作成します。
プロンプトでAngular routingはあり、スタイルシートにはSCSSを選択しました。Angular routingは本エントリで扱いませんが、次回以降で使用していく予定です。
❯ ng new my-app ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? SCSS [ https: //sass-lang.com/documentation/syntax#scss ] CREATE my-app/README.md (1023 bytes) CREATE my-app/.editorconfig (274 bytes) CREATE my-app/.gitignore (631 bytes) CREATE my-app/angular.json (3654 bytes) CREATE my-app/package.json (1249 bytes) CREATE my-app/tsconfig.base.json (458 bytes) CREATE my-app/tsconfig.json (426 bytes) CREATE my-app/tslint.json (3184 bytes) CREATE my-app/.browserslistrc (853 bytes) CREATE my-app/karma.conf.js (1018 bytes) CREATE my-app/tsconfig.app.json (292 bytes) CREATE my-app/tsconfig.spec.json (338 bytes) CREATE my-app/src/favicon.ico (948 bytes) CREATE my-app/src/index.html (291 bytes) CREATE my-app/src/main.ts (372 bytes) CREATE my-app/src/polyfills.ts (2835 bytes) CREATE my-app/src/styles.scss (80 bytes) CREATE my-app/src/test.ts (753 bytes) CREATE my-app/src/assets/.gitkeep (0 bytes) CREATE my-app/src/environments/environment.prod.ts (51 bytes) CREATE my-app/src/environments/environment.ts (662 bytes) CREATE my-app/src/app/app-routing.module.ts (245 bytes) CREATE my-app/src/app/app.module.ts (393 bytes) CREATE my-app/src/app/app.component.scss (0 bytes) CREATE my-app/src/app/app.component.html (25757 bytes) CREATE my-app/src/app/app.component.spec.ts (1059 bytes) CREATE my-app/src/app/app.component.ts (211 bytes) CREATE my-app/e2e/protractor.conf.js (869 bytes) CREATE my-app/e2e/tsconfig.json (299 bytes) CREATE my-app/e2e/src/app.e2e-spec.ts (639 bytes) CREATE my-app/e2e/src/app.po.ts (301 bytes) ✔ Packages installed successfully. Successfully initialized git.
作成された my-app
ディレクトリに移動しておきます。
❯ cd my-app/
アプリケーションのビルド・起動
ng serveでアプリをビルド、起動します。
--open
オプションをつけると自動でブラウザが開きます。
ng serve
はファイルの変更を検知し、自動でリビルドしてくれるので、以降の作業では起動しっぱなしにしておきます。
❯ ng serve --open Compiling @angular/core : es2015 as esm2015 Compiling @angular/animations : es2015 as esm2015 Compiling @angular/compiler/testing : es2015 as esm2015 Compiling @angular/core/testing : es2015 as esm2015 Compiling @angular/animations/browser : es2015 as esm2015 Compiling @angular/common : es2015 as esm2015 Compiling @angular/platform-browser : es2015 as esm2015 Compiling @angular/common/http : es2015 as esm2015 Compiling @angular/common/testing : es2015 as esm2015 Compiling @angular/platform-browser-dynamic : es2015 as esm2015 Compiling @angular/platform-browser/testing : es2015 as esm2015 Compiling @angular/router : es2015 as esm2015 Compiling @angular/animations/browser/testing : es2015 as esm2015 Compiling @angular/common/http/testing : es2015 as esm2015 Compiling @angular/forms : es2015 as esm2015 Compiling @angular/platform-browser/animations : es2015 as esm2015 Compiling @angular/platform-browser-dynamic/testing : es2015 as esm2015 Compiling @angular/router/testing : es2015 as esm2015 chunk {main} main.js, main.js.map (main) 60.6 kB [initial] [rendered] chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 141 kB [initial] [rendered] chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered] chunk {styles} styles.js, styles.js.map (styles) 12.9 kB [initial] [rendered] chunk {vendor} vendor.js, vendor.js.map (vendor) 2.65 MB [initial] [rendered] Date: 2020-08-09T13:42:30.673Z - Hash: e069bd65d556c23a289b - Time: 18402ms ** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ ** : Compiled successfully.
http://localhost:4200/ が開き、以下の初期画面が表示されました。
生成されたAppコンポーネントの確認と編集
初期画面の実装は src/app/app.component.html
です。このファイルを以下のように書き換えます。
<h1>{{ title }}</h1>
保存すると、自動的にコンパイルされ、変更後のページが読み込まれます。
このHTMLは app.component.ts
の@Componentデコレータに指定されたtemplateUrlで設定されています。
{{ title }}
はこのモジュールでエクスポートしてあるクラス AppComponent
のプロパティ title
の値を参照しています。
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'my-app'; }
@ComponentのselectorはコンポーネントをHTML上に埋め込む際に使用するセレクタです。
src/index.html
を確認するとbody部に <app-root>
が記述され、Appコンポーネントが組み込まれていることがわかります。
<body> <app-root></app-root> </body>
selectorはCSSセレクタなので、id属性で指定する場合は selector: '#app-root'
、 class属性で指定する場合は selector: '.app-root'
となります。その時、テンプレートはそれぞれ <div id="app-root"></div>
と <div class="app-root"></div>
のようになります。
上記のHTMLをChromeのデベロッパーツールで確認するとこんな感じです。
スタイルは@ComponentのstyleUrlsで指定されています。配列なので複数指定可能です。
AppComponent
に設定されたスタイルシート app.component.scss
を変更してみます。
h1 { color: red; }
スタイルが適用され、フォントの色が変わりました。
コンポーネントの作成
ユーザの一覧を表示するコンポーネント user-list
をng generateで作成します。
❯ ng g c user-list CREATE src/app/user-list/user-list.component.scss (0 bytes) CREATE src/app/user-list/user-list.component.html (24 bytes) CREATE src/app/user-list/user-list.component.spec.ts (643 bytes) CREATE src/app/user-list/user-list.component.ts (287 bytes) UPDATE src/app/app.module.ts (485 bytes)
作成したコンポーネントはAppModule
で@NgModuleのdeclarationsに自動的に追加されます。
// ... import { UserListComponent } from './user-list/user-list.component'; // 追加 @NgModule({ declarations: [ AppComponent, UserListComponent //追加 ], // ...
生成されたテンプレートでは user-list works!
とだけ表示されます。
<p>user-list works!</p>
コンポーネントの実装は以下の通りです。
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-user-list', templateUrl: './user-list.component.html', styleUrls: ['./user-list.component.scss'] }) export class UserListComponent implements OnInit { constructor() { } ngOnInit(): void { } }
UserListコンポーネントの表示
まずは自動生成されたコンポーネントをそのまま表示してみます。
AppComponent
のテンプレートに <app-user-list>
を追記します。
<h1>{{ title }}</h1> <app-user-list></app-user-list>
user-list.component.html
の内容が表示されました。
ユーザ一覧の表示
Userクラスの作成
ユーザを表現するクラス User
を作成します。
❯ ng g class user --type=model CREATE src/app/user.model.spec.ts (152 bytes) CREATE src/app/user.model.ts (22 bytes)
user.model.ts
の User
クラスでコンストラクタに必要なプロパティを定義します。
username
のみ必須で後は任意な項目としました。
export class User { constructor(private username: string, private firstName?: string, private lastName?:string, private email?: string) { } }
ユーザ一覧を返すプロパティを実装
User
クラスをインポートして、適当な User
オブジェクトを users
で返します。
import { User } from '../user.model'; // ... export class UserListComponent implements OnInit { // ... get users() { let user1 = new User('foo'); let user2 = new User('bar', 'John', 'Doe', 'foo@example.com'); return [user1, user2] } }
Userオブジェクトをループして表示
テンプレートで*ngForを使ってユーザ一覧を表示します。
<table> <thead> <tr> <th>Username</th> <th>First Name</th> <th>Last Name</th> <th>Email</th> </tr> </thead> <tbody> <tr *ngFor="let user of users"> <td>{{ user.username }}</td> <td>{{ user.firstName }}</td> <td>{{ user.lastName }}</td> <td>{{ user.email }}</td> </tr> </tbody> </table>
スタイルシートでは枠線を設定しておきます。
table, th, td { border: 1px solid black; border-collapse: collapse; }
以下のように User
オブジェクトの一覧が表示できました。
REST APIでユーザ一覧を取得
次にユーザの一覧をREST APIで取得するように変更します。
APIの実装
APIのモックをjson-serverで用意します。
❯ npm install -g json-server
/users
で2件のユーザ情報を返すように設定します。
{ "users": [ { "username": "foo"}, { "username": "bar", "firstName": "John", "lastName": "Doe", "email": "foo@example.com"} ] }
サーバを起動します。
❯ json-server --watch db.json
これで、 http://localhost:3000/users にGETリクエストを投げると db.json
に記述したJSONを返すようになりました。
❯ curl http://localhost:3000/users [ { "username": "foo" }, { "username": "bar", "firstName": "John", "lastName": "Doe", "email": "foo@example.com" } ]
HttpClientModuleのインポート
HTTPリクエストを扱うため、HttpClientModuleをインポートします。
import { HttpClientModule } from '@angular/common/http'; // 追加 // ... @NgModule({ // ... imports: [ BrowserModule, AppRoutingModule, HttpClientModule // 追加 ], // ... }) export class AppModule { }
サービスの作成
APIを叩くサービスクラスを作成します。
❯ ng g service api CREATE src/app/api.service.spec.ts (342 bytes) CREATE src/app/api.service.ts (132 bytes)
生成された api.service.ts
に以下のコードを追加します。
- HttpClientをインポート
- コンストラクタでHttpClientをインジェクト
fetch()
メソッドでHttpClientを使用し、http://localhost:3000/users にGETリクエスト
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; // 追加 @Injectable({ providedIn: 'root' }) export class ApiService { constructor(private httpClient: HttpClient) { } // HttpClientをインジェクト fetch(){ // 追加 return this.httpClient.get('http://localhost:3000/users'); } }
UserListコンポーネントからAPIを実行
最後に UserListComponent
のコンストラクタで ApiService
をインジェクトし、ngOnInitで users
プロパティにAPIから取得したJSONを設定します。
User
クラスを用いた実装は不要なので削除しました。
import { Component, OnInit } from '@angular/core'; import { ApiService } from '../api.service'; // 追加 @Component({ selector: 'app-user-list', templateUrl: './user-list.component.html', styleUrls: ['./user-list.component.scss'] }) export class UserListComponent implements OnInit { users = [] // 追加 constructor(private apiService: ApiService) { } // サービスをインジェクト ngOnInit(): void { this.apiService.fetch().subscribe((data: any[])=>{ // 追加 this.users = data; }) } }
これでAPIから取得したユーザ一覧を表示することができました。
さいごに
ここまでの実装は以下のリポジトリに格納しておきました。
次回以降ではルーティングの設定や、マテリアルデザインの導入、Firebaseとの連携等を試していく予定です。