自作アプリ「BookSelf」のAngular部分の解説
前記事に書いたBookSelfのAngular部分の解説となります。
Angular部分はangular CLIを使用して作成しました。
言語はTypeScriptになります。
起動
cd BookSelfApp ng serve
構成
ソースの構成は以下のような形です。
src │ app.module.ts │ ├─component │ home.component.css │ home.component.html │ home.component.ts │ router.component.ts │ ├─model │ bookInfo.ts │ bookItem.ts │ ├─profile │ profile.ts │ └─service │ bookapi.service.ts │ bookself.database.service.ts │ └─common http.service.ts
以下のような方針でディレクトリは分けています。
component
画面(component単位)を格納するディレクトリ
画面に対してロジック(TypeScript)、HTML、CSSを分けて格納するディレクトリ
model
データオブジェクト(言い方が難しい。JavaではJOJO?)を格納するディレクトリ
profile
環境情報を格納するディレクトリ
UI
UIデザインにはbootstrapを使用しています。
npm install --save bootstrap
"apps" : [ ... "styles" : [ "../node_modules/bootstrap/dist/css/bootstrap.min.css", "styles.css" ],
※ng-bootstrapもインストールしてますがこちらはまだ使用していないです。
今回はいったんこんな感じの構成で作成しました。
いろいろ考えましたが、経験が増えていくうちにこれから変わってくかもしれません。
わかりずらく、いろいろ調べたところ
自分の記録用と同じことで迷った人の参考までに
■app.module.tsへの記載
AngularCLIを使用している場合はapp.module.tsになるがその指定はmain.tsとなります。
さらにはangular-cli.jsonで起動もとをmain.tsに決めています。(あとindex.htmlとかも)
・Componentを追加や削除の場合
ngModuleのdeclarationsに記載をする
・ライブラリの機能を追加したい場合
モジュールのimportを記載し、ngModuleのimportにも記載する
・constructorでインスタンス化する場合(DI)
ngModuleのproviderに記載をする
※HttpとかはHttpModuleの内部でproviderの宣言がされているのでHttpModuleをImportすることで解決している
・最初の起動画面
ngModuleのbootstrapに記載
■インクリメンタルサーチ
検索フォームはインクリメンタルサーチを作っています。(必要だろうか。。。)
f: FormGroup; public constructor(private fb: FormBuilder, ....) {...}
fというフォームグループの宣言とFormBuilderのDIをします。
this.f = this.fb.group({ 'searchWord': ['', Validators.required] }); this.f.valueChanges.debounceTime(500).subscribe(value => { this.searchWord = value['searchWord']; this.bookapiService.search(this.searchWord).subscribe(value => { this.bookItems = value[0]; this.totalItems = value[1]; this.initPaginationList(this.page); }); });
これをngOnInit(最初に動く)で実装しています。
searchWordフォームコントロールをFormBuilderに設定します。
Validators.requiredは指定フィールドが必須という意味らしい。今回はあまり意識しないです。
値に変更がかかってから次の変更を検知するまで500ミリ秒待ちを入れてます。無駄に反応しすぎるのをさけるためです。
変更を受けて検索処理が入るようになり、インクリメンタルサーチ的な動きをつくっています。
<form class="form-search" [formGroup]="f"> <div class="form-group"> <input type="text" value="utf8" formControlName="searchWord" class="form-control" placeholder="Please enter keywords"> </div> </form>
フォームは以下のような形で上記のフォームグループfの紐づけとsearchWordの紐づけをします。
※参考
qiita.com
qiita.com
■APIの結果を受けて(この結果も使用する)、さらにAPIを投げる場合
参考(動作未確認、ソースではbookapi.service.tsで実装例あり)
//結果をObservable型でComponentのsubcribeに返すことですべての結果を非同期でわたせるっぽい return http.request(最初のAPI) .map(res => { let result = res.json(); return result; }) .map(result => { firstApiResult = result; let reses = [];//複数のAPI結果の格納先 for(var i in result){ let res = http.request(次のAPI, i) .map(res => { let result = res.json(); return result; }); reses.push(res); } return reses; }) .flatMap(reses => Observable.forkJoin(reses))//flatMapとObservable.forkJoinを使用することで最初のAPI結果を待って、次のAPIも非同期で処理できる .map(secondApiResults => { return [firstApiResult, secondApiResults];//secondApiResultsは配列 });
※参考
Angular2でObservableを使ってHTTPリクエストを複数送信 | VPSサーバーでWebサイト公開 備忘録 ~Linux、MySQLからAJAXまで
アプリ作成前にWeb以外では以下の本を参考にさせてもらっています。
Webアプリケーション作りの基本的なところは押さえられると思います。
Angular2によるモダンWeb開発 TypeScriptを使った基本プログラミング
- 作者: 末次章
- 出版社/メーカー: 日経BP社
- 発売日: 2017/01/18
- メディア: 単行本
- この商品を含むブログ (1件) を見る
今回のAngularのソースはGitHubにコミットしてます。
github.com
自作のWebAPI部分(DBも)がないと動きません。
その部分に関しての詳細は次の記事に記載します。