DEV Community

Cover image for Angular 16 Full Calendar load data problems
Felipe Leviñir
Felipe Leviñir

Posted on

Angular 16 Full Calendar load data problems

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)
  };
}
Enter fullscreen mode Exit fullscreen mode

}

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;
});
Enter fullscreen mode Exit fullscreen mode

}

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);
Enter fullscreen mode Exit fullscreen mode

}

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)