The issue I'm experiencing is due to a delay in asynchronous data loading in my Angular app that uses FullCalendar. Initially, when the component loads, the calendar shows the data, but when I navigate between months, no data is shown, but when I go back in the months, the calendar data appears.
`import { Component, OnInit, ViewChild, TemplateRef } from '@angular/core';
import { RecursoFuncionarioService } from 'src/app/services/recurso-funcionario.service';
import { Response } from 'src/app/helpers/classes/response';
import { CalendarOptions } from '@fullcalendar/core';
import { FullCalendarComponent } from '@fullcalendar/angular';
import dayGridPlugin from '@fullcalendar/daygrid';
import esLocale from '@fullcalendar/core/locales/es';
@Component({
selector: 'app-consulta-horario',
templateUrl: './consulta-horario.component.html',
styleUrls: ['./consulta-horario.component.scss']
})
export class ConsultaHorarioComponent implements OnInit {
calendarOptions?: CalendarOptions;
asistenciaDiaria: any;
datosAsistencia: { [fecha: string]: { entradaHora: string, salidaHora: string, entradaSede: string, salidaSede: string, horasTrabajadas: string } } = {};
diasFeriadoLegal: { [key: string]: boolean } = {};
diasPermisoAdministrativo: { [key: string]: boolean } = {};
diasLicenciaMedica: { [key: string]: boolean } = {};
datosCargados = false;
@ViewChild('fullcalendar') fullcalendar?: FullCalendarComponent;
@ViewChild('eventContent') eventContentTemplate?: TemplateRef;
constructor(
private recursoFuncionarioService: RecursoFuncionarioService,
) {
this.asistenciaDiaria = [{}];
}
ngOnInit(): void {
this.cargaInicial();
}
cargaInicial(): void {
const fecha = new Date();
this.Load(fecha, true);
}
LoadCalendar(): void {
if(this.datosCargados){
this.calendarOptions = {
plugins: [
dayGridPlugin,
],
initialView: 'dayGridMonth',
firstDay: 1,
fixedWeekCount: true,
showNonCurrentDates: false,
editable: false,
weekends: true,
dayMaxEvents: true,
locale: esLocale,
eventContent: this.eventContentTemplate,
headerToolbar: {
left: 'prev,next',
center: 'title',
right: 'today'
},
datesSet: (dateInfo) => {
this.Load(dateInfo.start, false);
},
dayCellDidMount: this.dayCellDidMount.bind(this)
};
}
}
Load(fecha: Date, isInitialLoad: boolean): void {
this.recursoFuncionarioService.AsistenciaDiariaGetItems(fecha).subscribe((response: Response) => {
this.asistenciaDiaria = response.Data;
this.procesarDatosAsistencia();
if (isInitialLoad) {
this.LoadCalendar();
}
});
}
procesarDatosAsistencia(): void {
const events = this.asistenciaDiaria.flatMap((item) => {
const dia = new Date(item.Dia);
if (item.ConFeriadoLegal) {
this.diasFeriadoLegal[dia.toISOString().split('T')[0]] = true;
}
if (item.ConPermisoAdministrativo) {
this.diasPermisoAdministrativo[dia.toISOString().split('T')[0]] = true;
}
if (item.ConLicenciaMedica) {
this.diasLicenciaMedica[dia.toISOString().split('T')[0]] = true;
}
this.datosAsistencia[dia.toISOString().split('T')[0]] = {
entradaHora: item.EntradaHora ? this.formatTime(item.EntradaHora) : '',
salidaHora: item.SalidaHora ? this.formatTime(item.SalidaHora) : '',
entradaSede: item.EntradaSede || '',
salidaSede: item.SalidaSede || '',
horasTrabajadas: item.MinutosTrabajados ? this.formatWorkTime(item.MinutosTrabajados) : ''
};
this.datosCargados = true;
});
}
dayCellDidMount(arg): void {
const fecha = arg.date.toISOString().split('T')[0];
const datosDia = this.datosAsistencia[fecha];
const esFeriadoLegal = !!this.diasFeriadoLegal[fecha];
const esPermisoAdministrativo = !!this.diasPermisoAdministrativo[fecha];
const esLicenciaMedica = !!this.diasLicenciaMedica[fecha];
const iconContainer = document.createElement('div');
iconContainer.style.position = 'absolute';
iconContainer.style.bottom = '0';
iconContainer.style.right = '0';
iconContainer.style.padding = '5px';
if (datosDia) {
const asistenciaContainer = document.createElement('div');
asistenciaContainer.style.position = 'absolute';
asistenciaContainer.style.left = '0';
asistenciaContainer.style.top = '0';
asistenciaContainer.style.padding = '5px';
asistenciaContainer.style.textAlign = 'left';
asistenciaContainer.style.fontSize = '0.80rem';
asistenciaContainer.style.fontWeight = 'bold';
if (datosDia.entradaHora && datosDia.entradaSede) {
const contenedorEntrada = document.createElement('div');
const iconEntrada = document.createElement('i');
iconEntrada.className = 'pi pi-arrow-right';
iconEntrada.style.color = 'green';
contenedorEntrada.appendChild(iconEntrada);
const textoEntrada = document.createTextNode(` ${datosDia.entradaHora} - ${datosDia.entradaSede}`);
contenedorEntrada.appendChild(textoEntrada);
asistenciaContainer.appendChild(contenedorEntrada);
}
if (datosDia.salidaHora && datosDia.salidaSede) {
const contenedorSalida = document.createElement('div');
const iconSalida = document.createElement('i');
iconSalida.className = 'pi pi-arrow-left';
iconSalida.style.color = 'red';
contenedorSalida.appendChild(iconSalida);
const textoSalida = document.createTextNode(` ${datosDia.salidaHora} - ${datosDia.salidaSede}`);
contenedorSalida.appendChild(textoSalida);
asistenciaContainer.appendChild(contenedorSalida);
}
if (datosDia.horasTrabajadas) {
const contenedorHoras = document.createElement('div');
const iconHoras = document.createElement('i');
iconHoras.className = 'pi pi-clock';
iconHoras.style.color = 'blue';
contenedorHoras.appendChild(iconHoras);
const textoHoras = document.createTextNode(` ${datosDia.horasTrabajadas} Horas Trabajadas`);
contenedorHoras.appendChild(textoHoras);
asistenciaContainer.appendChild(contenedorHoras);
}
arg.el.appendChild(asistenciaContainer);
}
if (esFeriadoLegal) {
const iconFeriado = document.createElement('i');
iconFeriado.className = 'pi pi-calendar';
iconFeriado.style.color = 'green';
iconContainer.appendChild(iconFeriado);
}
if (esPermisoAdministrativo) {
const iconPermisoAdministrativo = document.createElement('i');
iconPermisoAdministrativo.className = 'pi pi-briefcase';
iconPermisoAdministrativo.style.color = 'orange';
iconContainer.appendChild(iconPermisoAdministrativo);
}
if (esLicenciaMedica) {
const iconLicenciaMedica = document.createElement('i');
iconLicenciaMedica.className = 'pi pi-calendar-plus';
iconLicenciaMedica.style.color = 'red';
iconContainer.appendChild(iconLicenciaMedica);
}
arg.el.style.position = 'relative';
arg.el.appendChild(iconContainer);
}
formatTime(dateTimeString: string): string {
const date = new Date(dateTimeString);
let hours = date.getHours().toString().padStart(2, '0');
let minutes = date.getMinutes().toString().padStart(2, '0');
let seconds = date.getSeconds().toString().padStart(2, '0');
return ${hours}:${minutes}:${seconds}
;
}
formatWorkTime(MinutosTrabajados: number): string {
const horas = Math.floor(MinutosTrabajados / 60);
const minutos = MinutosTrabajados % 60;
return [
horas.toString().padStart(2, '0'),
minutos.toString().padStart(2, '0')
].join(':');
}
}
`
Top comments (0)