Ionic+Firebaseでパスワード制限つきチャットアプリ(6)RxJSを用いてデータの受け渡し(うまくいかず)
Angular+Firebaseでパスワード制限つきチャットアプリの作成方法が解説されている以下のサイトをIonic3に少し改変しながら写経している。
https://qiita.com/Yamamoto0525/items/a76ea4b3924eeb82b0f9
前回は、「Angularのルーティング設定(基礎編)」まで(曲りなりに)写経した。
http://twosquirrel.mints.ne.jp/?p=23987
今回は、続きの、「AngularのRxJSを使ってデータの受け渡しをする」からやっていきたい。
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
Observableを実装する際は、
●データを流す(next)
●データを受け取る(subscribe)
ことが必要になる。
<実装例>
src/pages/login/login.ts
ionic serve で起動すると、consoleにtext1が表示された5秒後に、text2が表示された。
この時点でのソースコード(変更部分)
https://github.com/adash333/ionic3_firebase_chat2/commit/d4206d6804721f04c980c168fa6e01c4791932e5
(2)任意のタイミングでデータを流すSubject
クリックなどのイベントをトリガーとしてデータを処理したいような場合、Subjectクラスというものを使用する。
Subjectクラスのインスタンスは、Observableとoberverの2つの役割を同時に担うことができるため、任意のタイミングでデータを流すことができるらしい。。。(???)
src/pages/login/login.ts
確認用 login.html
Nextボタンを押すたびに、consoleに1, 2, 3, 4, … と数字が表示されていくのが確認できた。面白い!(なお、このときはオフラインでした。。。)
git push しておく。
ここまでのソースコード。
(3)sessionサービスを作る
Angularのコンポーネント間のデータの授受の方法は、以下のようなものがあるらしい。
● @Input, @Outputを使って親子間でデータを授受
● ルーターのdataを用いて、異なるルート間のデータを授受
● サービスをDI(Dependency Injection)して、異なるコンポーネント間のデータを授受
● RxJSを使って、異なるコンポーネント間のデータを授受
今回は、sessionサービス(Ionicでは、session provider でしょうか?)を作成して、各コンポーネントにDI(Dependency Injection)して、「ログインしているかどうか」を異なるコンポーネント間で共有したいと思います。
ターミナル(cmd.exe)で、
ionic g provider session
Ionic CLIからsession providerを作成したので、ちゃんと、src/app/app.module.ts に、SessionProviderがimportされていた。
作成したSession Providerの中に、Session用のプロパティを追加する。なお、Sessonモデルは、src/models/ フォルダ の中にsession.ts を作成し、Sessionクラスを定義しておく。
src/models/sesion.ts (新規作成)
src/providers/session/session.ts
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
AngularではSeviceという名前らしいが、Ionicでは、Providerという名前になる。
(SessionService ではなく、SessionProvider となる。)
ionic serve してみると、以下のエラー
app.module.ts にHttpClientModule をimport して、imports: [] のところにもHttpClientModule を追加してみる。
OK.
HomePage(home.ts)と、SignUpPage(sign-up.ts)にも同様の追加をしておく。
ううむ、ヘッダーをコンポーネントとして分離しておけば、楽だったかもしれない。。。
(5)RxJSを使って、異なるコンポーネント間のデータを授受する。
RxJSを使って、LoginPageで変更したSessionの値を、(LoginPage自身、 =>よく分からないので今回はあきらめることとしました。)HomePage、SignUpPageに反映させます。
まず、SessionProviderにlogin関数と、logout関数を作成。
src/providers/session/session.ts
src/models/session.ts に、reset() を定義
写経元サイトによると、observerをsessionSubject、ObservableをsessionStateとして宣言し、ログイン、ログアウト時にはログインセッションを変更してストリームに流すよう設定しているとのこと。
ここで、ionic serveすると、以下のようなエラー
home.ts の、sessionService関連を全てコメントアウトしたところ、次はこんなエラー。
”NullInjectorError: No provider for NavController!”
ググったところ、
https://github.com/ionic-team/ionic/issues/9581
Service(つまり、provider)では、ViewControllerまたはNavControllerを使ってはいけません。(なにー!?)
とのこと。自分で勝手に書き換えたsession.ts のnavController関連のところをコメントアウトすると、画面が戻った。。。
しかし、どうしようか。。。と一瞬思ったが、SessionProviderにはnavCtrollerを用いたページ遷移のコードは入れずに、それぞれのページのtsファイルに、ページ遷移のコードを記載すればよいだけであった。
src/pages/login/login.ts
src/pages/login/login.html の変更
「ログイン」をクリックすると、home.html に行く。
左上の「←」をクリックすると、ログインページに戻る。
(6)LoginPageにsessionサービスをDI(Dependency Injection)し、login関数を参照する。
ログインボタンをクリックしたときに、sessionSubject(observer)のnext()が発火し、sessionState(Observable)を通して他のページにSessionの値を渡す。
以下は、ページ遷移をしているこちらのコードでは実際上は意味のない実装であるが、「ログイン状態での分岐」の練習として、写経元サイトにしたがって、やってみる。
src/pages/home/home.ts
home.html
home.html のヘッダーの右側に、Logout の文字は表示されたが、クリックしてもページが遷移しない。LoginPageからHomePageへ移動する際に、navCtrl.push() 関数を使用しているため、HomePageからLoginPageへ戻るためには、navCtrl.pop() 関数を使う必要があるのだろうか?試しに、home.html のlogout() のところを、push(LoginPage)からpop()に変更してみる。
home.ts
全くだめであった。home.tsのionviewDidLoad()などをいじったりしてconsoleを見たりしてみたが、home.htmlに移動しても、sessionが読み込まれてい無さそうな感じであった。残念。
RsJSが全くできなかったが、今回はあきらめることとした。
ううむ、これ以降は以前にも増してボロボロな雰囲気である。
参考:https://ionicframework.com/docs/api/components/toolbar/Navbar/
git push
ここまでのソースコード
https://github.com/adash333/ionic3_firebase_chat2/tree/cb2f9a9406e2afc3e5ef68c1156ae9feb54fb2e5
ディスカッション
コメント一覧
まだ、コメントがありません