为什么 @ViewChild() 装饰器在使用 PrimeNG FullCalendar 的 Angular 组件中不起作用?
Why @ViewChild() decorator is not working in this Angular component using PrimeNG FullCalendar?
我在一个使用 PrimeNG FullCalendar 组件的简单 Angular 9 项目中发现了以下问题,这个:
https://primefaces.org/primeng/showcase/#/fullcalendar
这个 PrimeNG FullCalendar 组件是基于另一个 Angular 原始组件 https://fullcalendar.io/docs
我必须做什么:我必须实现一个外部可拖动事件,如此处所示:https://stackblitz.com/edit/fullcalendar-angular-demo?file=src%2Fapp%2Fapp.component.html
在前面的示例中,它使用了原始的 Fullcalendar.io 组件而不是 PrimeNG 组件,但作为 PrimeNG 对这个组件的包装,它应该是可能的。
我做了什么: 我创建了一个包含日历和处理简单事件的项目,如单击特定日期、单击特定事件、从日期移动事件到我日历中的另一个日期。
这里是我到目前为止实现的代码的存储库: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.
引用
然后我有一个 div 被 #external 引用,其中包含我需要拖到我的日历中的外部事件。
此外部事件拖动操作无效。
问题似乎取决于 typescript 组件代码无法访问此 div #external 引用。
在我的 fullcalendar.component.ts 文件中,我定义了这个 class 实现我的组件背后的逻辑(我正在按照提供的示例实现它):
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 参考。
我的假设正确吗?怎么了?我错过了什么?我该如何尝试修复此错误?
它不起作用,因为 ngOnInit
对于 ViewChild
来说太早了,有一个特殊的钩子 AfterViewInit
,所有 ViewChild
在触发时都已初始化例如,您可以访问 this.external.nativeElement
。
在这里您可以找到他们如何使用它的示例: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
}
}
尝试this.calendarComponent.getApi()
我在一个使用 PrimeNG FullCalendar 组件的简单 Angular 9 项目中发现了以下问题,这个: https://primefaces.org/primeng/showcase/#/fullcalendar
这个 PrimeNG FullCalendar 组件是基于另一个 Angular 原始组件 https://fullcalendar.io/docs
我必须做什么:我必须实现一个外部可拖动事件,如此处所示:https://stackblitz.com/edit/fullcalendar-angular-demo?file=src%2Fapp%2Fapp.component.html
在前面的示例中,它使用了原始的 Fullcalendar.io 组件而不是 PrimeNG 组件,但作为 PrimeNG 对这个组件的包装,它应该是可能的。
我做了什么: 我创建了一个包含日历和处理简单事件的项目,如单击特定日期、单击特定事件、从日期移动事件到我日历中的另一个日期。 这里是我到目前为止实现的代码的存储库: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.
引用然后我有一个 div 被 #external 引用,其中包含我需要拖到我的日历中的外部事件。
此外部事件拖动操作无效。
问题似乎取决于 typescript 组件代码无法访问此 div #external 引用。
在我的 fullcalendar.component.ts 文件中,我定义了这个 class 实现我的组件背后的逻辑(我正在按照提供的示例实现它):
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 参考。
我的假设正确吗?怎么了?我错过了什么?我该如何尝试修复此错误?
它不起作用,因为 ngOnInit
对于 ViewChild
来说太早了,有一个特殊的钩子 AfterViewInit
,所有 ViewChild
在触发时都已初始化例如,您可以访问 this.external.nativeElement
。
在这里您可以找到他们如何使用它的示例: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
}
}
尝试this.calendarComponent.getApi()