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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Ionic

Ionicは、クロスプラットフォームに対応したモバイルアプリ開発のためのオープンソースUIフレームワークです。iOSやAndroid、Webのアプリケーションを1つのコードベースで開発できます。

RxJS

RxJSは、Observablesを用いたリアクティブプログラミングのJavaScript向けの実装です。イベント駆動処理も含めた非同期処理を高い可読性を持って容易にコーディングできます。

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

1回答

2532閲覧

ionicカレンダーアプリ 日付ごとにイベントを判別できるようにしたい。

Gento

総合スコア77

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Ionic

Ionicは、クロスプラットフォームに対応したモバイルアプリ開発のためのオープンソースUIフレームワークです。iOSやAndroid、Webのアプリケーションを1つのコードベースで開発できます。

RxJS

RxJSは、Observablesを用いたリアクティブプログラミングのJavaScript向けの実装です。イベント駆動処理も含めた非同期処理を高い可読性を持って容易にコーディングできます。

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2019/08/28 08:15

編集2019/08/28 08:23

前提・実現したいこと

カレンダーアプリを制作しており、日付ごとのページでイベント操作をできるようにしたいです。

※参考画像
イメージ説明
イメージ説明

補足情報(FW/ツールのバージョンなど)

カレンダーのライブラリー: ionic2-calendar

ionic info

Ionic: Ionic CLI : 5.2.5 (/usr/local/lib/node_modules/ionic) Ionic Framework : @ionic/angular 4.7.1 @angular-devkit/build-angular : 0.801.3 @angular-devkit/schematics : 8.1.3 @angular/cli : 8.1.3 @ionic/angular-toolkit : 2.0.0 Cordova: Cordova CLI : 9.0.0 (cordova-lib@9.0.1) Cordova Platforms : none Cordova Plugins : no whitelisted plugins (0 plugins total) Utility: cordova-res : 0.6.0 native-run : 0.2.8 System: NodeJS : v10.15.1 (/usr/local/bin/node) npm : 6.4.1 OS : macOS Mojave Xcode : Xcode 10.2.1 Build version 10E1001

参考にしたサイト:

idを使った画面遷移を参考にした

カレンダーとFirebaseの接続を参考にした

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

日付ごとにイベントを判別できない。

イベントのidをパラメーターとして渡すために以下のようにしました。

html

1<ion-header> 2 <ion-toolbar color="danger"> 3 <ion-buttons slot="start"> 4 <ion-menu-button></ion-menu-button> 5 </ion-buttons> 6 <ion-title> 7 {{ viewTitle }} 8 </ion-title> 9 <ion-buttons slot="end"> 10 <ion-button (click)="today()">Today</ion-button> 11 </ion-buttons> 12 </ion-toolbar> 13</ion-header> 14 15<ion-content padding> 16 17 <calendar [eventSource]="eventSource" 18 [calendarMode]="calendar.mode" 19 [currentDate]="calendar.currentDate" 20 (onCurrentDateChanged)="onCurrentDateChanged($event)" 21 (onEventSelected)="onEventSelected($event)" 22 (onTitleChanged)="onViewTitleChanged($event)" 23 (onTimeSelected)="onTimeSelected($event)" 24 [locale]="calendar.locale" 25 *ngFor="let dayEvent of (dayEvents | async)" 26 [routerLink]="['/day', dayEvent.id]" 27 > 28</calendar> 29 30<ion-list> 31 <ion-item *ngFor="let dayEvent of (dayEvents | async)"> 32 <!-- 全イベントのidが取れる --> 33 <p>{{ dayEvent.id }}</p> 34 </ion-item> 35</ion-list> 36</ion-content>

すると、イベントの数だけカレンダーが作成されます(*ngForなので当たり前ですが)

Firebaseにイベントが3つあるとして、idが a, b, c とします。
するとカレンダーが3つ作成され、一番上のカレンダーのどこを押してもidがaとなり、真ん中のカレンダーのどこを押してもidがbとなり、、、

という感じです。

カレンダーが1つで、かつ日付ごとにイベントを判別できない状態です。

仮に5日にイベントがあったとして、5日を押すと5日のページに遷移し、イベントありと表記されている。6日を押すと6日のページに遷移するが、イベントなしと表記されている。

このような状態にしたいです。

該当のソースコード

home.page.html

html

1<ion-header> 2 <ion-toolbar color="danger"> 3 <ion-buttons slot="start"> 4 <ion-menu-button></ion-menu-button> 5 </ion-buttons> 6 <ion-title> 7 {{ viewTitle }} 8 </ion-title> 9 <ion-buttons slot="end"> 10 <ion-button (click)="today()">Today</ion-button> 11 </ion-buttons> 12 </ion-toolbar> 13</ion-header> 14 15<ion-content padding> 16 17 <calendar [eventSource]="eventSource" 18 [calendarMode]="calendar.mode" 19 [currentDate]="calendar.currentDate" 20 (onCurrentDateChanged)="onCurrentDateChanged($event)" 21 (onEventSelected)="onEventSelected($event)" 22 (onTitleChanged)="onViewTitleChanged($event)" 23 (onTimeSelected)="onTimeSelected($event)" 24 [locale]="calendar.locale" 25 [routerLink]="['/day', dayEvent.id]" 26 > 27</calendar> 28 29<ion-list> 30 <ion-item *ngFor="let dayEvent of (dayEvents | async)"> 31 <!-- イベントのidは取れている --> 32 <p>{{ dayEvent.id }}</p> 33 </ion-item> 34</ion-list> 35</ion-content>

home.service.ts

typescript

1import { Injectable } from '@angular/core'; 2import { Observable } from 'rxjs'; 3import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore'; 4import { map, take } from 'rxjs/operators'; 5 6export interface DayEvent { 7 id?: string; 8 title: string; 9 endTime: Date; 10 startTime: Date; 11 allDay: boolean; 12} 13 14@Injectable({ 15 providedIn: 'root' 16}) 17export class HomeService { 18 // 取得したコレクションを格納 19 private dayCollection: AngularFirestoreCollection<DayEvent>; 20 // コレクションのストリームを格納 21 private dayEvents: Observable<DayEvent[]>; 22 23 eventSource = []; 24 selectedDate = new Date(); 25 26 constructor( 27 private afs: AngularFirestore 28 ) 29 { 30 // コレクションを取得してdayCollectionに格納 31 this.dayCollection = this.afs.collection<DayEvent>(`events`); 32 this.dayEvents = this.dayCollection.snapshotChanges().pipe( 33 map(actions => { 34 return actions.map(a => { 35 const event = a.payload.doc.data(); 36 const id = a.payload.doc.id; 37 return { id, ...event }; 38 }); 39 }) 40 ); 41 } 42 43 getEvents(): Observable<DayEvent[]> { 44 return this.dayEvents; 45} 46 47 getEvent(id: string) { 48 return this.dayCollection.doc<DayEvent>(id).valueChanges().pipe( 49 take(1), 50 map(dayEvent => { 51 dayEvent.id = id; 52 console.log('getEventで取った ' + dayEvent.id); 53 return dayEvent; 54 }) 55 ); 56 } 57 58 addNewEvent() { 59 const start = this.selectedDate; 60 const end = this.selectedDate; 61 end.setMinutes(end.getHours() + 1); 62 const event = { 63 title: 'Event #' + start.getMinutes(), 64 startTime: start, 65 endTime: end, 66 allDay: true 67 }; 68 console.log('イベント登録' + start); 69 // this.db.collection(`users/${this.authService.userId}/events`); 70 return this.afs.collection(`events`).add(event); 71 } 72 73 deleteEvent(id: string): Promise<void> { 74 return this.afs.collection(`events`).doc(id).delete(); 75 } 76 77}

home.page.ts

typescript

1import { AngularFirestore } from '@angular/fire/firestore'; 2import { HomeService, DayEvent } from './home.service'; 3import { Component, OnInit } from '@angular/core'; 4import { Router } from '@angular/router'; 5import { Observable } from 'rxjs'; 6 7@Component({ 8 selector: 'app-home', 9 templateUrl: 'home.page.html', 10 styleUrls: ['home.page.scss'], 11}) 12export class HomePage implements OnInit { 13 eventSource = []; 14 viewTitle; 15 calendar = { 16 mode: 'month', 17 currentDate: new Date(), 18 locale: 'ja-JP' 19 }; 20 21 // ここでのプロパティがhtmlで使われる 22 private dayEvents: Observable<DayEvent[]>; 23 24 25 constructor( 26 private router: Router, 27 private homeService: HomeService, 28 private db: AngularFirestore 29 ) { 30 // Firebaseからイベント取得 31 this.db.collection(`events`).snapshotChanges().subscribe(colSnap => { 32 this.eventSource = []; 33 colSnap.forEach(snap => { 34 const event: any = snap.payload.doc.data(); 35 event.id = snap.payload.doc.id; 36 event.startTime = event.startTime.toDate(); 37 event.endTime = event.endTime.toDate(); 38 this.eventSource.push(event); 39 }); 40 }); 41 42 } 43 44 45 ngOnInit() { 46 this.dayEvents = this.homeService.getEvents(); 47 } 48 49 onViewTitleChanged(title) { 50 this.viewTitle = title; 51 } 52 53 54 55 onEventSelected(event) { 56 console.log('Event selected:' + event.startTime + '-' + event.endTime + ',' + event.title); 57 } 58 59 // 選択した日付を取得&サービスのaddNewEventを設定 60 onTimeSelected(ev) { 61 const selected = new Date(ev.selectedTime); 62 console.log('選択した日は ' + selected); 63 this.homeService.selectedDate = selected; 64 } 65 66 onCurrentDateChanged(event: Date) { 67 } 68 69 reloadSource(ev) { 70 console.log('range changed: startTime: ' + ev.startTime + ', endTime: ' + ev.endTime); 71 } 72 73 74 today() { 75 this.calendar.currentDate = new Date(); 76 } 77}

day.page.html

html

1<ion-header> 2 <ion-toolbar> 3 <ion-buttons slot="start"> 4 <ion-back-button defaultHref="/home"></ion-back-button> 5 </ion-buttons> 6 <ion-buttons slot="end"> 7 <ion-button (click)="addNewEvent()">登録</ion-button> 8 </ion-buttons> 9 <ion-title> 10 Dayページ 11 </ion-title> 12 </ion-toolbar> 13</ion-header> 14 15<ion-content> 16 <ion-button (click)="deleteEvent()">削除</ion-button> 17 <!-- ここのidのイベントが削除される --> 18 <p>{{ dayEvent.id }}</p> 19</ion-content>

day.page.ts

typescript

1import { HomeService, DayEvent } from './../home/home.service'; 2import { Component, OnInit } from '@angular/core'; 3import { Router, ActivatedRoute } from '@angular/router'; 4import { ToastController } from '@ionic/angular'; 5 6 7@Component({ 8 selector: 'app-day', 9 templateUrl: './day.page.html', 10 styleUrls: ['./day.page.scss'], 11}) 12 13export class DayPage implements OnInit { 14 eventSource = []; 15 viewTitle; 16 selectedDate = new Date(); 17 18 dayEvent: DayEvent = { 19 title: '', 20 startTime: this.selectedDate, 21 endTime: this.selectedDate, 22 allDay: true 23 }; 24 id = null; 25 26 constructor( 27 private homeService: HomeService, 28 private router: Router, 29 private activatedRoute: ActivatedRoute, 30 private toastCtrl: ToastController, 31 ) { 32 } 33 34 ngOnInit() { 35 // idを取得 36 this.id = this.activatedRoute.snapshot.paramMap.get('id'); 37 } 38 39 ionViewWillEnter() { 40 if (this.id) { 41 this.homeService.getEvent(this.id).subscribe(dayEvent => { 42 this.dayEvent = dayEvent; 43 }); 44 } 45 } 46 47 48 addNewEvent() { 49 this.homeService.addNewEvent().then(() => { 50 this.router.navigateByUrl('/'); 51 }); 52 } 53 54 deleteEvent() { 55 this.homeService.deleteEvent(this.dayEvent.id).then(() => { 56 this.router.navigateByUrl('/'); 57 this.showToast('削除しました'); 58 }, 59 err => { 60 this.showToast('問題が発生しました。削除できなかったです。'); 61 }); 62 } 63 64 showToast(msg) { 65 this.toastCtrl.create({ 66 message: msg, 67 duration: 2000 68 }).then(toast => toast.present()); 69 } 70}

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gento

2019/08/29 05:29

わかりました。
guest

回答1

0

ベストアンサー

ngforのループに番号持たせてみてはどうでしょうか?

ngFor="let item of items; let i = index

iにて日付処理する。という感じで。

たぶん僕はこんな感じで逃げてると思います。

投稿2019/08/28 22:23

Skyus

総合スコア29

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gento

2019/08/29 05:35

ngForでループを回している限り、イベントの数だけカレンダーが作成されると思うのですが、、、 しかし、ループ1つ1つに処理をできるというのは、参考になりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問