質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.91%

Angularのサービスを使って、イベントデータをFirebaseから取得したい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 392

Gento

score 43

前提・実現したいこと

ionic + firebaseでカレンダーアプリを制作しています。
カレンダーはionic2-calendarを使っています。
追加したイベントをfirebaseのCloud Firestoreから読み込むのは、こちらを参考にうまくいきました。

しかし、各日にちのページ(下の動画を参照)でイベントの削除や更新といった事を考えると、こちらのコードの様にサービスでデータを取得した方が良いのでは?と思い、挑戦しています。

カレンダーページ

選択した日のページ

ここに質問の内容を詳しく書いてください。
home.service.tsには

発生している問題・エラーメッセージ

home.page.ts

import { AuthService } from './../auth/auth.service';
import { AngularFirestore } from '@angular/fire/firestore';
import { HomeService, DayEvent } from './home.service';
import { Component, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';
import { Router } from '@angular/router';
import { EventData } from './home.model';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
  eventSource = [];
  viewTitle;
  calendar = {
    mode: 'month',
    currentDate: new Date(),
    locale: 'ja-JP'
  };

  //private events: Observable<DayEvent[]>;

  constructor(
    private navCtrl: NavController,
    private router: Router,
    private homeService: HomeService,
    private db: AngularFirestore
  ) {
    this.db.collection(`events`).snapshotChanges().subscribe(colSnap => {
      this.eventSource = [];
      colSnap.forEach(snap => {
       const event: any = snap.payload.doc.data();
       event.id = snap.payload.doc.id;
       event.startTime = event.startTime.toDate();
       event.endTime = event.endTime.toDate();
       this.eventSource.push(event);
        });
      });
    }

//getEventsはhome.service.tsから呼ばれた
  ngOnInit() {
    // this.events = this.homeService.getEvents();
  }

  onViewTitleChanged(title) {
    this.viewTitle = title;
  }



  onEventSelected(event) {
    console.log('Event selected:' + event.startTime + '-' + event.endTime + ',' + event.title);
  }

  onTimeSelected(ev) {
    const selected = new Date(ev.selectedTime);
    this.homeService.selectedDate = selected;
  }

  reloadSource(ev) {
    console.log('range changed: startTime: ' + ev.startTime + ', endTime: ' + ev.endTime);
  }


  today() {
    this.calendar.currentDate = new Date();
  }

  dayPage() {
    this.router.navigateByUrl('/day');
  }

}

home.service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { map, take } from 'rxjs/operators';

export interface DayEvent {
  id?: string;
  title: string;
  startTime: Date;
  endTime: Date;
  allDay: boolean;
}

@Injectable({
  providedIn: 'root'
})
export class HomeService {
  private dayCollection: AngularFirestoreCollection<DayEvent>;
  private dayEvents: Observable<DayEvent[]>;
  private colEvents;


  eventSource = [];
  selectedDate = new Date();

  constructor(
    private afs: AngularFirestore
  )
  {
    this.dayCollection = this.afs.collection(`events`);
    this.colEvents =  this.dayCollection.snapshotChanges().subscribe(colSnap => {
      this.eventSource = [];
      colSnap.forEach(snap => {
        const event: any = snap.payload.doc.data();
        event.id = snap.payload.doc.id;
        event.startTime = event.startTime.toDate();
        event.endTime = event.endTime.toDate();
       //イベントはログに出るが、画面に反映されない。
        console.log(event);
        return this.eventSource.push(event);
      });
    });





  }

//これをhome.page.tsで呼ぶ
  getEvents(): Observable<DayEvent[]> {
    return this.colEvents;
  }


  addNewEvent() {
    const start = this.selectedDate;
    const end = this.selectedDate;
    end.setMinutes(end.getMinutes() + 60);

    const event = {
       title: 'Event #' + start.getMinutes(),
       startTime: start,
       endTime: end,
       allDay: true
    };
    console.log('イベント登録' + start);
     //this.db.collection(`users/${this.authService.userId}/events`);
    return this.afs.collection(`events`).add(event);
  }

  onEventSelected(event) {
    return console.log('イベント選ばれた:' + event.startTime + '-' + event.endTime + ',' + event.title);
  }

  onTimeSelected(ev) {
    return console.log(ev.selectedTime + ', hasEvents: ' +
      (ev.events !== undefined && ev.events.length !== 0) + ', disabled: ' + ev.disabled);
  }


  reloadSource(ev) {
    return console.log('range changed: startTime: ' + ev.startTime + ', endTime: ' + ev.endTime);
  }





}

home.service.tsには、どのようにコードを書けば良いでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ionicや使用されているライブラリについて知見はありませんが、Angularの観点で回答します。

home.service.tsには、どのようにコードを書けば良いでしょうか?

メソッド内でsnapshotChangesを次のように処理してObservable<DayEvent[]>を返してあげれば良いと思うのですがいかがでしょう。

export class HomeService {
  constructor(private afs: AngularFirestore) {}

  getEvents(): Observable<DayEvent[]> {
    return this.afs.collection<DayEvent>('events').snapshotChanges().map((actions) => {
        return actions.map((action) => {
            const data = action.payload.doc.data() as DayEvent;
            const id = action.payload.doc.id;

            return { id, ...data };
        });
    });
  }
}


そしてそれをngOnInitで呼び出してみてください。

export class HomePage implements OnInit {
  events: Observable<DayEvent[]>;

  constructor(
    private navCtrl: NavController,
    private router: Router,
    private homeService: HomeService
  ) {}

  ngOnInit() {
    this.events = this.homeService.getEvents();
  }
}

あとはAsyncPipe を使ってeventsをビューにバインドしてあげれば良いと思います。
ちなみに、上記ソースコードは未検証なので、参考としてみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/28 12:02

    ありがとうございます。
    参考に試してみます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る