问题
I am using ap-fullcalendar for angular/typescript. I have a data service, where I get the events for the calendar from my database, I wrap the data in a Behaviour Subject and subscribe to it and make it into an observable from another function. I have a data service because I have multiple subscriptions to the same observable. In my component where the calendar is, I subscribe to the data. However, for some reason, the events are not getting passed properly to the calendar and won't show up. I have manually entered some values for events, to check the calendar works fine, which it does. I have outputted what I get from my service (shown below) and it looks fine. What could the issue be?
Data service:
@Injectable()
export class SubjectEventsService {
allData: EventSchema[] = new Array<EventSchema>();
allData$: BehaviorSubject<EventSchema[]>;
constructor(private afs : AngularFirestore) {
//Get subjectEvents collection on initialise
this.subjectEventCollection = this.afs.collection('subjectEvents');
this.getSubjectEvents();
}
getSubjectEvents(subjectFilter?:string){
if(!this.allData$){
this.allData$ = <BehaviorSubject<EventSchema[]>> new BehaviorSubject(new Array<EventSchema>());
this.subjectEventCollection.valueChanges().pipe(
map(res => {
let result : EventSchema[] = [];
res.map(subjectEvent => {
let eventSchema : EventSchema[] = subjectEvent.eventData;
eventSchema.forEach(event => {
result.push(event as EventSchema);
})
})
console.log(result);
return result;
}))
.subscribe(events => {
console.log(events);
this.allData = events;
console.log(this.allData);
this.allData$.next(events);
});
}
}
subscribeToDataServiceGetSubjectEvents(): Observable<EventSchema[]> {
console.log(this.allData$);
return this.allData$.asObservable();
}
}
Home component (where calendar is):
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit{
calendarOptions: any;
displayEvent: any;
@ViewChild(CalendarComponent) ucCalendar: CalendarComponent;
name: string;
subjectFilter: string;
allData$: Observable<EventSchema[]>;
constructor(private subjectEventsService: SubjectEventsService, private dialog: MatDialog) { }
ngOnInit(){
this.subjectEventsService.subscribeToDataServiceGetSubjectEvents().subscribe(data=>{
let data$:any = data;
console.log("fun");
console.log(data);
this.calendarOptions = {
editable: true,
eventLimit: false,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listMonth'
},
events: data$,
//WORKS FINE WITH THIS DATA ENTERED MANUALLY
// [{
// end: "2018-08-13T19:00:00",
// price: 10,
// start:"2018-08-13T17:00:00",
// title:"Forces"
// }],
eventClick: (calEvent, jsEvent, view) => {
this.openDialog(calEvent);
// console.log('Event: ' + calEvent.title);
// console.log('View: ' + view.name);
}
};
});
}
}
}
Output from subscribe (this is an acceptable format required by the calendar):
Array(4)
0:{end: "2018-08-13T19:00:00", price: 10, start: "2018-08-13T17:00:00", title: "Forces"}
1:{end: "2018-08-19T13:00:00", price: 10, start: "2018-08-19T11:00:00", title: "Energy"}
2:{end: "2018-08-15T20:00:00", price: 10, start: "2018-08-15T17:00:00", title: "Trigonometry"}
3:{end: "2018-08-25T11:00:00", price: 10, start: "2018-08-25T08:00:00", title: "Mechanics"}
回答1:
The only way this appears to work is calling through the ViewChild. The two key parts of this are this.calendar.fullCalendar('removeEvents');
and this.calendar.fullCalendar('addEventSource', events);
in your subscription, so in your instance, something like this should work:
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit{
calendarOptions:Object = {
editable: true,
eventLimit: false,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listMonth'
},
events: [],
eventClick: (calEvent, jsEvent, view) => {
this.openDialog(calEvent);
}
};
displayEvent: any;
@ViewChild(CalendarComponent) ucCalendar: CalendarComponent;
name: string;
subjectFilter: string;
allData$: Observable<EventSchema[]>;
constructor(private subjectEventsService: SubjectEventsService, private dialog: MatDialog) { }
ngOnInit(){
this.subjectEventsService.subscribeToDataServiceGetSubjectEvents().subscribe(data=>{
this.ucCalendar.fullCalendar('removeEvents');
this.ucCalendar.fullCalendar('addEventSource', data);
});
}
}
}
My test project (for sanity)
export class CalComponent implements OnInit {
@ViewChild('calendar') calendar;
_events = new BehaviorSubject<Event[]>(EVENTS);
events$ = this._events.asObservable();
constructor(private http:HttpClient) { }
ngOnInit() {
}
onCalendarInit(e:boolean) {
if(e) {
this.events$.subscribe((events) => {
this.calendar.fullCalendar('removeEvents');
this.calendar.fullCalendar('addEventSource', events);
});
}
}
count:number = 1;
nextEvent() {
this.count++;
EVENTS.push({id: 10 + this.count, title: "Hello!", start: `2018-08-${this.count}`});
this._events.next(EVENTS);
}
calendarOptions:Object = {
height: '600px',
fixedWeekCount : false,
defaultDate: '2016-09-12',
editable: true,
eventLimit: true,
events: [] //Nothing needed here
};
}
interface Event {
id?:number;
title:string;
start:string;
end?:string;
}
Html
<button (click)="nextEvent()">Click for next event</button>
<angular2-fullcalendar #calendar [options]="calendarOptions" (initialized)="onCalendarInit($event)"></angular2-fullcalendar>
More Info
来源:https://stackoverflow.com/questions/51886066/full-calendar-passing-event-data-from-observable-not-showing-up-on-calendar