Angular 16 Full Calendar加载数据问题

问题描述 投票:0回答:1

我遇到的问题是由于使用 FullCalendar 的 Angular 应用程序中的异步数据加载滞后造成的。最初,当组件加载时,日历显示为空,因为它是在异步数据(例如事件或每日出勤信息)可用之前呈现的。然后,当我在月份之间导航时,日历最终显示数据,表明数据加载和更新当时正常工作,但在应用程序首次启动期间无法正常工作。

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 interactionPlugin from '@fullcalendar/interaction';
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<any>;

  constructor(
    private recursoFuncionarioService: RecursoFuncionarioService,
  ) { 
    this.asistenciaDiaria = [{}];
  }

  ngOnInit(): void {
    this.cargaInicial();
  }

  cargaInicial(): void {
    const fecha = new Date();
    this.Load(fecha);
  }
  
  Load(fecha: Date) {
    this.recursoFuncionarioService.AsistenciaDiariaGetItems(fecha).subscribe((response: Response) => {
      this.asistenciaDiaria = response.Data;

      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;
        this.LoadCalendar();
      });
    });
  }

  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);
        },
        dayCellDidMount: (arg) => {
  
          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(':');
  }

}
    <div class="grid">
        <div class="col-12">
            <div class="view-titulo">Consulta horario</div>
        </div>
    </div>
    
    <div class="flex justify-content-evenly flex-wrap p-3">
        <div>
            <i class="pi pi-arrow-right" style="color: green"></i>
            <label class="pl-2">Entrada</label>
        </div>
        <div>
            <i class="pi pi-arrow-left" style="color: red"></i>
            <label class="pl-2">Salida</label>
        </div>
        <div>
            <i class="pi pi-clock" style="color: blue"></i>
            <label class="pl-2">Horas trabajadas</label>
        </div>
        <div>
            <i class="pi pi-calendar-plus" style="color: red"></i>
            <label class="pl-2">Licencia médica</label>
        </div>
        <div>
            <i class="pi pi-calendar" style="color: green"></i>
            <label class="pl-2">Feriado Legal</label>
        </div>
        <div>
            <i class="pi pi-briefcase" style="color: orange"></i>
            <label class="pl-2">Permiso Administrativo</label>
        </div>
    </div>
    
    <div class="grid">
        <div class="col-12">
                <full-calendar class="full-calendar-custom"
                    *ngIf="calendarOptions"
                    #fullcalendar
                    [dayCellDidMount]="dayCellDidMount"
                    [options]="calendarOptions">
              </full-calendar>
        </div>
    </div>
</div>```
angular fullcalendar angular16 fullcalendar-6
1个回答
0
投票

您可以使用 Angular 的 ResolveFn。基本上,您将从路由器调用数据提供程序功能。一旦您的异步数据提供程序函数获取所有数据,它就会加载组件。您将在 onInit 函数中准备好数据,没有任何延迟。

请参阅我写的解释此过程的另一个答案https://stackoverflow.com/a/77517484/5822844

© www.soinside.com 2019 - 2024. All rights reserved.