如何解决我可以在 FullCalendar 中将结束日期设置为仅一个单元格的特定结束日期吗?
在 FullCalendarJS 中,我们都知道有一个很长的事件会在日历中显示一个扩展的水平条。我想要做的是仅在 1 个单元格中显示开始日期以及结束日期。我已经可以做开始日期,但结束日期不能移动到它想要的单元格/日期。例如,请截图如下:
开始日期为 2021 年 3 月 26 日,而结束日期应为 2021 年 3 月 30 日。
这是我的打字稿代码:
import { Component,OnInit,ElementRef,Input,Output,EventEmitter,AfterViewInit } from '@angular/core';
import { Calendar } from '@fullcalendar/core';
import { CalendarService } from '@services/calendar.service';
import { CALENDAR_FILTERS } from '@shared/constants';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import moment from 'moment';
const MINI = 'mini-calendar';
const FULL = 'full-calendar';
@Component({
selector: 'app-calendar',templateUrl: './calendar.component.html',styleUrls: ['./calendar.component.scss']
})
export class CalendarComponent implements OnInit,AfterViewInit {
calendarFilters: any;
calendar: Calendar;
isLoading: boolean;
@Input() eventSource: (startDate: any,endDate: any,callback: any,filters: any) => any;
@Input() withFilters: boolean;
@Input() appearance: string;
@Output() onDateClick = new EventEmitter();
@Output() onEventClick = new EventEmitter();
constructor(private elementRef: ElementRef,private calendarService: CalendarService) {}
ngOnInit(): void {}
ngAfterViewInit() {
if (this.withFilters) {
this.calendarService.fetchCalendarFilters().subscribe((res) => {
this.calendarFilters = res.calendar_filter
? JSON.parse(res.calendar_filter.config)
: CALENDAR_FILTERS.slice(0);
this.initializeCalendar();
this.addCalendarFiltersSection();
});
return;
}
this.initializeCalendar();
}
initializeCalendar() {
let calendarEl = document.getElementById('common-calendar');
this.calendar = new Calendar(calendarEl,{
plugins: [dayGridPlugin,interactionPlugin],header: {
left: this.appearance == MINI ? 'title' : '',center: this.appearance == MINI ? '' : 'title',right: 'prev,today,next'
},eventSources: [this.fetchEvents.bind(this)],dateClick: this.dateClick.bind(this),eventClick: this.eventClick.bind(this),displayEventEnd: true,eventTimeFormat: {
hour: 'numeric',minute: '2-digit',meridiem: 'short'
},eventRender: function(info) {
let el = info.el;
let data = info.event;
el.childNodes[0].remove();
let title = document.createElement("p");
var bold = document.createElement("strong");
title.appendChild(document.createTextNode(data.title));
title.classList.add("cstm-fc-title");
el.appendChild(title);
let time = document.createElement("p");
let start = moment(data.start).format('hh:mm A');
let end = moment(data.end).add(1,'days').format('hh:mm A');
time.appendChild(document.createTextNode(start.concat(' - ',end)));
time.classList.add("cstm-fc-time");
el.appendChild(time);
},eventPositioned: function(info) {
let el = info.el;
if (info.event.extendedProps.event_type === 'placed') {
el.parentElement.removeAttribute("colspan");
el.parentElement.setAttribute("colspan","1");
}
}
});
this.calendar.render();
}
refetchEvents() {
this.calendar.refetchEvents();
}
fetchEvents(info,successCallback,failureCallback) {
this.eventSource(info.startStr,info.endStr,this.calendarFilters);
}
dateClick(info) {
this.onDateClick.emit(info)
}
eventClick(info) {
this.onEventClick.emit(info);
}
onCalendarFilterClick(event) {
this.isLoading = true;
const calendar_event = event.target.id;
this.calendarFilters.includes(calendar_event)
? this.calendarFilters.splice(this.calendarFilters.indexOf(calendar_event),1)
: this.calendarFilters.push(calendar_event);
this.calendarService.setCalendarFilters({ config: this.calendarFilters }).subscribe(calendar => {
this.isLoading = false;
});
this.generateButtonEventFilters(this.calendarFilters);
this.calendar.refetchEvents();
}
setLoader(value) {
this.isLoading = value;
}
private addCalendarFiltersSection() {
var el = this.elementRef.nativeElement.querySelector('.fc-view-container');
let html = '<div class="btn-group-events" id="custom-buttons"></div>';
el.insertAdjacentHTML('beforebegin',html);
this.generateButtonEventFilters(this.calendarFilters);
}
private generateButtonEventFilters(calendarFilters) {
let buttons = '';
CALENDAR_FILTERS.forEach(function (event,index) {
buttons += `<button type="button" id="${event}" class="${
calendarFilters.includes(event) ? 'btn-event' : 'btn-event btn-event-active'
}">
${event.charAt(0).toUpperCase() + event.substring(1)}</button>`;
});
document.getElementById('custom-buttons').innerHTML = buttons;
this.addHandlers();
}
private addHandlers() {
CALENDAR_FILTERS.forEach((calendar_event) => {
this.elementRef.nativeElement.querySelector(`#${calendar_event}`).addEventListener('click',(event) => {
this.onCalendarFilterClick(event);
});
});
}
}
非常感谢任何建议。
解决方法
所以我已经解决了这个问题,我的解决方法是使用 VanillaJS
和一些 FullCalendar 的 event
回调来操作 endDate。
这是最后的样子:
我已经使用了 eventRender
和 eventPositioned
回调,然后在控制台上检查了返回的 info
对象。从那里,我结合一些 Vanilla JS 操纵它。
eventRender: function(info) {
let el = info.el;
let data = info.event;
el.childNodes[0].remove();
let title = document.createElement("p");
title.appendChild(document.createTextNode(data.title));
title.classList.add("cstm-fc-title");
el.appendChild(title);
let time = document.createElement("p");
let start = moment(data.start).format('hh:mm A');
let end = moment(data.end).add(1,'days').format('hh:mm A');
time.appendChild(document.createTextNode(start.concat(' - ',end)));
time.classList.add("cstm-fc-time");
el.appendChild(time);
},eventPositioned: function(info) {
let el = info.el;
let parent = el.parentElement;
if (info.event.extendedProps.event_type === 'placed') {
if (el.classList.contains("fc-start")) {
parent.removeAttribute("colspan");
parent.setAttribute("colspan","1");
}
if (el.classList.contains("fc-end")) {
let columnNumber = parseInt(parent.getAttribute("colspan")) + 1;
let endDateColumn = parent.parentElement.querySelector("td:nth-child(" + columnNumber + ")");
parent.classList.remove("fc-event-container");
parent.removeAttribute("class");
parent.removeAttribute("colspan");
parent.childNodes.forEach(function(item) {
let clone = item.cloneNode(true);
endDateColumn.appendChild(clone);
endDateColumn.classList.add("fc-event-container");
endDateColumn.setAttribute("colspan","1");
el.remove();
});
}
}
}