FullCalendar has an add-on called Scheduler which I am trying to use with PrimeNG-Schedule component. Looking at the PrimeNG docs, there is an 'options' property that I can use to send arbitrary information to FullCalendar. This does work but when I hook up to data retrieval to an async API, it causes issues.
API uses Observables which I then subscribe to in the component. This works fine for Events as the view gets updated automatically when events are changed.
However, when supplying the FullCalendar with 'resources' via the PrimeNG 'options' property, things don't work as expected because the code to set the 'options' property is run before the API call has a chance to come back and is thus empty.
I am sure of this because if I hard-code the resources, things work.
I can think of a few ways to remedy the issue:
Make the calls synchronous (would like to avoid this)
Wait for all data to load and then (re)render the view (makes this almost the same as #1)
Configure the options.resources property such that when it changes, the view gets updated, just like it does for events (this is the best option but not sure if it's even possible)
I would appreciate any help. Thank you.
<p-schedule
[events]="events"
[businessHours]="businessHours"
[options]="optionConfig"
>
</p-schedule>
My (for now) dummy API
getEvents() {
return this.http
.get('assets/api/mockEvents.json')
.map((response : Response) => <Appointment[]>response.json().data)
.catch(this.handleError);
}
getResources() {
return this.http
.get('assets/api/mockResources.json')
.map((response : Response) => <Resource[]>response.json().data)
.catch(this.handleError);
}
Component file
ngOnInit() {
this.schedulerService.getEvents()
.subscribe(events=> this.events = events);
this.schedulerService.getResources()
.subscribe(resources => this.resources = resources);
// ***** If the following code is uncommented, resources are displayed in Schedule view ****
// this.resources = [
// new Resource(1, "Dr. Hibbert", "blue", true, new BusinessHours("08:00", "16:00")),
// new Resource(2, "Dr. Simpson", "green", true, new BusinessHours("10:00", "18:00"))
// ];
this.optionConfig = {
"resources": this.resources
}
}
Edit: One thing I thought of is, setting the this.resources
property only via it's setter method. This way, I know exactly when the value is being set, but the problem still remains how can I push the new value to schedule component after it has been initialized.
I Got it!
Using *ngIf
to delay rendering of the component until this.resources
has data. I added a new boolean property isDataAvailable
defaulting it to false. Then, this.schedulerService.getResources()
sets it to true
only after resources API call returns, at which point I also set the resources
property in optionConfig
ngOnInit() {
this.loadResources();
}
private loadResources() {
this.schedulerService.getResources()
.subscribe(
resources => {
this.resources = resources;
this.optionConfig['resources'] = this.resources;
this.isDataAvailable = true;
} ,
error => console.log(error)
);
}
Template:
<div *ngIf="isDataAvailable; else elseBlock">
<p-schedule
[events]="appointments"
[options]="optionConfig"
(onDayClick)="handleDayClick($event)"
(onEventClick)="handleEventClick($event)"
(onViewRender)="loadAppointments($event)">
</p-schedule>
</div>
<ng-template #elseBlock>Loading....</ng-template>