スポンサーリンク

Ionic+Firebaseでパスワード制限つきチャットアプリ(6)RxJSを用いてデータの受け渡し(うまくいかず)

Angular+Firebaseでパスワード制限つきチャットアプリの作成方法が解説されている以下のサイトをIonic3に少し改変しながら写経している。

https://qiita.com/Yamamoto0525/items/a76ea4b3924eeb82b0f9
image_thumb_thumb_thumb_thumb_thumb

前回は、「Angularのルーティング設定(基礎編)」まで(曲りなりに)写経した。

Ionic+Firebaseでパスワード制限つきチャットアプリ(5)navCtrl.push()でページ遷移

今回は、続きの、「AngularのRxJSを使ってデータの受け渡しをする」からやっていきたい。

image_thumb2_thumb_thumb_thumb_thumb

git version 2.16.1.windows.4
Sourcetree Version 2.4.8.0
firebase-tools
firebase@4.8.0
angularfire2@5.0.0-rc.4
promise-polyfill@8.0.0

npm install --save firebase@4.8.0
npm install --save angularfire2@5.0.0-rc.4
npm install --save promise-polyfill

 

(0)今回行うこと

●AngularのRxJS
●sessionサービスを作る

(1)AngularのRxJS

RxJSは、Reactive Extensions for JavaScript の略らしい。

リクエストのPromiseとストリームのObservable

写経元のサイトの以下の図が、本当に分かりやすいです。

https://qiita.com/Yamamoto0525/items/efc0e5617c7427fea86a
image

image

Observableを実装する際は、

●データを流す(next)
●データを受け取る(subscribe)

ことが必要になる。

<実装例>

src/pages/login/login.ts

(変更前)
image

(変更後)
image

ionic serve で起動すると、consoleにtext1が表示された5秒後に、text2が表示された。

image

image

この時点でのソースコード(変更部分)

https://github.com/adash333/ionic3_firebase_chat2/commit/d4206d6804721f04c980c168fa6e01c4791932e5

(2)任意のタイミングでデータを流すSubject

クリックなどのイベントをトリガーとしてデータを処理したいような場合、Subjectクラスというものを使用する。

Subjectクラスのインスタンスは、Observableとoberverの2つの役割を同時に担うことができるため、任意のタイミングでデータを流すことができるらしい。。。(???)

src/pages/login/login.ts

(変更前)
image

(変更後)
image

確認用 login.html

(変更後)
image

image

Nextボタンを押すたびに、consoleに1, 2, 3, 4, … と数字が表示されていくのが確認できた。面白い!(なお、このときはオフラインでした。。。)

git push しておく。

image

ここまでのソースコード。

 

(3)sessionサービスを作る

Angularのコンポーネント間のデータの授受の方法は、以下のようなものがあるらしい。

● @Input, @Outputを使って親子間でデータを授受

● ルーターのdataを用いて、異なるルート間のデータを授受

● サービスをDI(Dependency Injection)して、異なるコンポーネント間のデータを授受

● RxJSを使って、異なるコンポーネント間のデータを授受

今回は、sessionサービス(Ionicでは、session provider でしょうか?)を作成して、各コンポーネントにDI(Dependency Injection)して、「ログインしているかどうか」を異なるコンポーネント間で共有したいと思います。

ターミナル(cmd.exe)で、

ionic g provider session

image

Ionic CLIからsession providerを作成したので、ちゃんと、src/app/app.module.ts に、SessionProviderがimportされていた。

image

作成したSession Providerの中に、Session用のプロパティを追加する。なお、Sessonモデルは、src/models/ フォルダ の中にsession.ts を作成し、Sessionクラスを定義しておく。

src/models/sesion.ts (新規作成)

image

src/providers/session/session.ts

(変更前)
image

(変更後)
image

src/models/session.ts に記載したように、初期状態ではsession.loginが false となり、ログイン時はこのプロパティが true となることで状態を判断します。

このプロパティ(session.login が true か flase かどうか)を、他のコンポーネントで共有する場合は、DI(Dipendency Injection)を行って、プロパティの値を渡します。

(4)Session ProviderをLoginPage, HomePage(, SignInPage)にDIする。

本当は、ヘッダーをcomponent化して全てのページで共通化しておけば、そこに1回だけLSessionProviderをDIすればよいという利点があった。

しかし、今回はヘッダーをcomponent化していないので、LoginPageとHomePageの両方に、SessionProviderをDIする方針とする。

ページ数が10ページ以上になるようなサイトやアプリの場合は、ヘッダーをcomponent化しておいた方がよさそうだと感じた。

src/pages/login/login.ts

(変更前)
image

(変更後)
image

AngularではSeviceという名前らしいが、Ionicでは、Providerという名前になる。

(SessionService ではなく、SessionProvider となる。)

ionic serve してみると、以下のエラー

image

app.module.ts にHttpClientModule をimport して、imports: [] のところにもHttpClientModule を追加してみる。

src/app/app.module.ts
image

image

OK.

HomePage(home.ts)と、SignUpPage(sign-up.ts)にも同様の追加をしておく。

home.ts
image

image

sign-up.ts
image

ううむ、ヘッダーをコンポーネントとして分離しておけば、楽だったかもしれない。。。

(5)RxJSを使って、異なるコンポーネント間のデータを授受する。

RxJSを使って、LoginPageで変更したSessionの値を、(LoginPage自身、 =>よく分からないので今回はあきらめることとしました。)HomePage、SignUpPageに反映させます。

まず、SessionProviderにlogin関数と、logout関数を作成。

src/providers/session/session.ts

(変更前)
image

(変更後)
image

src/models/session.ts に、reset() を定義

image

写経元サイトによると、observerをsessionSubject、ObservableをsessionStateとして宣言し、ログイン、ログアウト時にはログインセッションを変更してストリームに流すよう設定しているとのこと。

ここで、ionic serveすると、以下のようなエラー

image

home.ts の、sessionService関連を全てコメントアウトしたところ、次はこんなエラー。

”NullInjectorError: No provider for NavController!”

ググったところ、

https://github.com/ionic-team/ionic/issues/9581
image

image

Service(つまり、provider)では、ViewControllerまたはNavControllerを使ってはいけません。(なにー!?)

とのこと。自分で勝手に書き換えたsession.ts のnavController関連のところをコメントアウトすると、画面が戻った。。。

image

しかし、どうしようか。。。と一瞬思ったが、SessionProviderにはnavCtrollerを用いたページ遷移のコードは入れずに、それぞれのページのtsファイルに、ページ遷移のコードを記載すればよいだけであった。

src/pages/login/login.ts

(変更前)
image

(変更後)
image

image

src/pages/login/login.html の変更

image

「ログイン」をクリックすると、home.html に行く。

image

左上の「←」をクリックすると、ログインページに戻る。

(6)LoginPageにsessionサービスをDI(Dependency Injection)し、login関数を参照する。

ログインボタンをクリックしたときに、sessionSubject(observer)のnext()が発火し、sessionState(Observable)を通して他のページにSessionの値を渡す。

以下は、ページ遷移をしているこちらのコードでは実際上は意味のない実装であるが、「ログイン状態での分岐」の練習として、写経元サイトにしたがって、やってみる。

src/pages/home/home.ts

(変更前)
image

(変更後)
image

image

image

home.html

(変更前)
image

(変更後)
image

home.html のヘッダーの右側に、Logout の文字は表示されたが、クリックしてもページが遷移しない。LoginPageからHomePageへ移動する際に、navCtrl.push() 関数を使用しているため、HomePageからLoginPageへ戻るためには、navCtrl.pop() 関数を使う必要があるのだろうか?試しに、home.html のlogout() のところを、push(LoginPage)からpop()に変更してみる。

home.ts

(変更前)
image

(変更後)
image

全くだめであった。home.tsのionviewDidLoad()などをいじったりしてconsoleを見たりしてみたが、home.htmlに移動しても、sessionが読み込まれてい無さそうな感じであった。残念。

RsJSが全くできなかったが、今回はあきらめることとした。

ううむ、これ以降は以前にも増してボロボロな雰囲気である。

home.html
image

参考:https://ionicframework.com/docs/api/components/toolbar/Navbar/
image

git push

image

ここまでのソースコード

https://github.com/adash333/ionic3_firebase_chat2/tree/cb2f9a9406e2afc3e5ef68c1156ae9feb54fb2e5

スポンサーリンク