为什么使用PrimeNG FullCalendar,@ ViewChild()装饰器在此Angular组件中不起作用?

I am very new with Angular and JavaScript\TypeScript technologies (I mainly came from Java) and I am finding the following problem working on a simple Angular 9 project that uses PrimeNG FullCalendar component, this one: https://primefaces.org/primeng/showcase/#/fullcalendar

This PrimeNG FullCalendar component is based on this other Angular original component https://fullcalendar.io/docs

WHAT I HAVE TO DO: I have to implement an external draggable events as done here: https://stackblitz.com/edit/fullcalendar-angular-demo?file=src%2Fapp%2Fapp.component.html

在前面的示例中,它使用的是原始Fullcalendar.io组件,而不是PrimeNG组件,但作为PrimeNG对该组件的包装,它应该是可能的。

WHAT I HAVE DONE: I created a project containing the calendar and handling simple event as click on a specific date, click on a specific event, moove an event from a date to another date in my calendar. Here the repository of the code implemented by me untill now: https://bitbucket.org/dgs_poste_team/soc_calendar/src/master/

我的问题是:如您所见,我的fullcalendar.component.hml文件包含以下代码:

<p>fullcalendar works!</p>

<div class="content-section implementation">
  <p-fullCalendar #fullcalendar
                  [events]="events"
                  [options]="options">
  </p-fullCalendar>
</div>

<div #external>
  <p>
    <strong>Draggable Events</strong>
  </p>
  <div class='fc-event'>My Event 1</div>
  <div class='fc-event'>My Event 2</div>
  <div class='fc-event'>My Event 3</div>
  <div class='fc-event'>My Event 4</div>
  <div class='fc-event'>My Event 5</div>
</div>

因此,p-fullCalendar是渲染我的日历的PrimeNG组件,并由#fullcalendar引用。

然后,我有一个#external引用的div,其中包含需要拖动到日历中的外部事件。

此外部事件拖动操作不起作用。

问题似乎取决于打字稿组件代码无法访问此div #external引用的事实。

在我的fullcalendar.component.ts文件中,我定义了此类,实现了组件背后的逻辑(我将按照提供的示例来实现):

import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { EventService } from '../event.service';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import listPlugin from '@fullcalendar/list';
import interactionPlugin, { Draggable } from '@fullcalendar/interaction';
import { FullCalendar } from 'primeng';

@Component({
  selector: 'app-fullcalendar',
  templateUrl: './fullcalendar.component.html',
  styleUrls: ['./fullcalendar.component.css']
})
export class FullcalendarComponent implements OnInit {

  events: any[];
  options: any;
  header: any;

  @ViewChild('fullcalendar') fullcalendar: FullCalendar;
  @ViewChild('external') external: ElementRef;

  constructor(private eventService: EventService) {}

  ngOnInit() {
    this.eventService.getEvents().then(events => { this.events = events;});
    //this.eventService.getEvents().then(res => {console.log(res)} )
    console.log("bla");
    //console.log(this.events.length);

    this.options = {
        plugins:[ dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin ],
        defaultDate: '2017-02-01',
        header: {
            left: 'prev,next',
            center: 'title',
            right: 'dayGridMonth,timeGridWeek,timeGridDay'
        },
        editable: true,

        dateClick: (dateClickEvent) =>  {         // <-- add the callback here as one of the properties of `options`
          console.log("DATE CLICKED !!!");
        },

        eventClick: (eventClickEvent) => {
          console.log("EVENT CLICKED !!!");
        },

        eventDragStop: (eventDragStopEvent) => {
          console.log("EVENT DRAG STOP !!!");
        }
    };


    console.log("external: " + this.external);
    console.log(this.fullcalendar.getCalendar().getEvents);

    new Draggable(this.external.nativeElement, {
      itemSelector: '.fc-event',
      eventData: function(eventEl) {
        return {
          title: eventEl.innerText
        };
      }
    });

  }

}

如您所见,我有两个由@ViewChild装饰的属性

@ViewChild('fullcalendar') fullcalendar: FullCalendar;
@ViewChild('external') external: ElementRef;

我认为由于某种原因,我无法理解这两行不能正常工作,因为在我的控制台中,我在此行上收到以下错误:

new Draggable(this.external.nativeElement, {
    ................................................
    ................................................
    ................................................
});

尝试访问this.external.nativeElement属性时,这是错误:

core.js:6272 ERROR TypeError: Cannot read property 'getCalendar' of undefined
    at FullcalendarComponent.ngOnInit (fullcalendar.component.ts:56)
    at callHook (core.js:4770)
    at callHooks (core.js:4734)
    at executeInitAndCheckHooks (core.js:4674)
    at refreshView (core.js:11998)
    at refreshComponent (core.js:13461)
    at refreshChildComponents (core.js:11701)
    at refreshView (core.js:12036)
    at renderComponentOrTemplate (core.js:12114)
    at tickRootContext (core.js:13668)

正如您在我的代码中看到的那样,我还将以下行添加到调试目的(添加到ngOnInit()方法中):

console.log("external: " + this.external);

控制台输出为:

external: undefined

因此在我看来,它无法访问#external div参考。

我的假设正确吗?怎么了?我想念什么?我该如何解决此错误?

评论
He猪
He猪

It doesn't work because ngOnInit is too early for ViewChild, there's a special hook for it AfterViewInit, all ViewChild will be initialised when it's triggered and you can access this.external.nativeElement for example.

Here you can find an example how they use it: https://angular.io/guide/lifecycle-hooks#responding-to-view-changes

export class AfterViewComponent implements  AfterViewInit {
  @ViewChild('external') external: ElementRef;

  ngAfterViewInit() {
    consoloe.log(this.external.nativeElement); // works
  }
}
点赞
评论