Полный календарь - передача данных о событиях из наблюдаемого - не отображается в календаре

Я использую ap-fullcalendar для angular/typcript. У меня есть служба данных, где я получаю события для календаря из своей базы данных, оборачиваю данные в объект поведения, подписываюсь на них и превращаю их в наблюдаемую из другой функции. У меня есть служба данных, потому что у меня есть несколько подписок на одну и ту же наблюдаемую. В моем компоненте, где находится календарь, я подписываюсь на данные. Однако, по некоторым причинам, события не передаются должным образом в календарь и не будут отображаться. Я вручную ввел некоторые значения для событий, чтобы проверить, что календарь работает нормально, что он делает. Я вывел то, что я получаю от моего сервиса (показано ниже), и он выглядит хорошо. В чем может быть проблема?

Служба данных:

@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();
  }
}

Домашний компонент (где календарь):

@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);
        }
      };
    });    
  }
  }
}

Вывод из подписки (это приемлемый формат, требуемый календарем):

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 ответ

Решение

Единственный способ, которым это работает, - это вызов через ViewChild. Две ключевые части этого this.calendar.fullCalendar('removeEvents'); а также this.calendar.fullCalendar('addEventSource', events); в вашей подписке, так что в вашем случае, что-то вроде этого должно работать:

@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);
    });    
  }
  }
}


Мой тестовый проект (для здравомыслия)


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>


Больше информации

Другие вопросы по тегам