Esta biblioteca de JavaScript para definir la información de Calendario es un clásico y la hemos usado mucho en los desarrollos de PHPRunner.
En React, está toda ella disponible y sirve todo lo que hemos aprendido de su uso en PHPRunner y es, todavía, más sencillo explotar todas sus funcionalidades desde el entorno de React.
En este artículo facilito 2 ejemplos (de la propia biblioteca), pero adaptados a la última versión de React.
Aunque espero que ya conozcáis cómo se puede saber las librerías instaladas utilizando el fichero «package.json«, voy a explicar qué es lo que he instalado en cada caso.
Objetivo
Comprobar la integración de FullCalendar en el entorno de React.
Demo1: https://fhumanes.com/fullcalendar-react/
Instalaciones:
npm install fullcalendar
npm install @fullcalendar/react
Demo2: https://fhumanes.com/scheduler-react/
Instalaciones:
npm install fullcalendar
npm install @fullcalendar/react
npm install @fullcalendar/resource
npm install @fullcalendar/resource-timeline
npm install @fullcalendar/adptive
Solución Técnica
Como os he indicado, los ejemplos los he recogido del proyecto que facilitan desde el producto https://github.com/fullcalendar/fullcalendar-examples, lo único que he hecho es ajustarlo a la forma en que construyo TODOS los proyectos de React y actualizar los módulos que utiliza.
En el siguiente artículo que escribiré, utilizaré la misma funcionalidad descrita en el artículo Guía 64 – Utilización de la biblioteca «FullCalendar», pero realizado en React.
Por si queréis consultar el código, os dejo lo más relevante de los ejemplos.
import React, { useState } from 'react' import { formatDate } from '@fullcalendar/core' import FullCalendar from '@fullcalendar/react' import dayGridPlugin from '@fullcalendar/daygrid' import timeGridPlugin from '@fullcalendar/timegrid' import interactionPlugin from '@fullcalendar/interaction' import { INITIAL_EVENTS, createEventId } from './event-utils' export default function DemoApp() { const [weekendsVisible, setWeekendsVisible] = useState(true) const [currentEvents, setCurrentEvents] = useState([]) function handleWeekendsToggle() { setWeekendsVisible(!weekendsVisible) } function handleDateSelect(selectInfo) { let title = prompt('Please enter a new title for your event') let calendarApi = selectInfo.view.calendar calendarApi.unselect() // clear date selection if (title) { calendarApi.addEvent({ id: createEventId(), title, start: selectInfo.startStr, end: selectInfo.endStr, allDay: selectInfo.allDay }) } } function handleEventClick(clickInfo) { if (window.confirm("Are you sure you want to delete the event "+clickInfo.event.title) ) { clickInfo.event.remove() } console.log("informa del clic en evento: ",clickInfo.event.id); } function handleEvents(events) { setCurrentEvents(events) } return ( <div className='demo-app'> <Sidebar weekendsVisible={weekendsVisible} handleWeekendsToggle={handleWeekendsToggle} currentEvents={currentEvents} /> <div className='demo-app-main'> <FullCalendar plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]} headerToolbar={{ left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay' }} initialView='dayGridMonth' editable={true} selectable={true} selectMirror={true} dayMaxEvents={true} weekends={weekendsVisible} initialEvents={INITIAL_EVENTS} // alternatively, use the `events` setting to fetch from a feed select={handleDateSelect} eventContent={renderEventContent} // custom render function eventClick={handleEventClick} eventsSet={handleEvents} // called after events are initialized/added/changed/removed /* you can update a remote database when these fire: eventAdd={function(){}} eventChange={function(){}} eventRemove={function(){}} */ /> </div> </div> ) } function renderEventContent(eventInfo) { return ( <> <b>{eventInfo.timeText}</b> <i>{eventInfo.event.title}</i> </> ) } function Sidebar({ weekendsVisible, handleWeekendsToggle, currentEvents }) { return ( <div className='demo-app-sidebar'> <div className='demo-app-sidebar-section'> <h2>Instructions</h2> <ul> <li>Select dates and you will be prompted to create a new event</li> <li>Drag, drop, and resize events</li> <li>Click an event to delete it</li> </ul> </div> <div className='demo-app-sidebar-section'> <label> <input type='checkbox' checked={weekendsVisible} onChange={handleWeekendsToggle} ></input> toggle weekends </label> </div> <div className='demo-app-sidebar-section'> <h2>All Events ({currentEvents.length})</h2> <ul> {currentEvents.map((event) => ( <SidebarEvent key={event.id} event={event} /> ))} </ul> </div> </div> ) } function SidebarEvent({ event }) { return ( <li key={event.id}> <b>{formatDate(event.start, {year: 'numeric', month: 'short', day: 'numeric'})}</b> <i>{event.title}</i> </li> ) }
import React from 'react' import { formatDate } from '@fullcalendar/core' import FullCalendar from '@fullcalendar/react' import adaptivePlugin from '@fullcalendar/adaptive' import dayGridPlugin from '@fullcalendar/daygrid' import timeGridPlugin from '@fullcalendar/timegrid' import interactionPlugin from '@fullcalendar/interaction' import resourceTimelinePlugin from '@fullcalendar/resource-timeline' import { INITIAL_EVENTS, createEventId } from './event-utils' const RESOURCES = [ { id: 'a', title: 'Auditorium A' }, { id: 'b', title: 'Auditorium B', eventColor: 'green' }, { id: 'c', title: 'Auditorium C', eventColor: 'orange' }, ] export default class DemoApp extends React.Component { state = { weekendsVisible: true, currentEvents: [] } render() { return ( <div className='demo-app'> {this.renderSidebar()} <div className='demo-app-main'> <FullCalendar plugins={[ adaptivePlugin, dayGridPlugin, timeGridPlugin, interactionPlugin, resourceTimelinePlugin, ]} headerToolbar={{ left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,resourceTimelineDay' }} initialView='resourceTimelineDay' editable={true} selectable={true} selectMirror={true} dayMaxEvents={true} weekends={this.state.weekendsVisible} initialEvents={INITIAL_EVENTS} // alternatively, use the `events` setting to fetch from a feed resources={RESOURCES} select={this.handleDateSelect} eventContent={renderEventContent} // custom render function eventClick={this.handleEventClick} eventsSet={this.handleEvents} // called after events are initialized/added/changed/removed /* you can update a remote database when these fire: eventAdd={function(){}} eventChange={function(){}} eventRemove={function(){}} */ /> </div> </div> ) } renderSidebar() { return ( <div className='demo-app-sidebar'> <div className='demo-app-sidebar-section'> <h2>Instructions</h2> <ul> <li>Select dates and you will be prompted to create a new event</li> <li>Drag, drop, and resize events</li> <li>Click an event to delete it</li> </ul> </div> <div className='demo-app-sidebar-section'> <label> <input type='checkbox' checked={this.state.weekendsVisible} onChange={this.handleWeekendsToggle} ></input> toggle weekends </label> </div> <div className='demo-app-sidebar-section'> <button onClick={this.handlePrint}>Print</button> </div> <div className='demo-app-sidebar-section'> <h2>All Events ({this.state.currentEvents.length})</h2> <ul> {this.state.currentEvents.map(renderSidebarEvent)} </ul> </div> </div> ) } handleWeekendsToggle = () => { this.setState({ weekendsVisible: !this.state.weekendsVisible }) } handleDateSelect = (selectInfo) => { let title = prompt('Please enter a new title for your event') let calendarApi = selectInfo.view.calendar calendarApi.unselect() // clear date selection if (title) { calendarApi.addEvent({ id: createEventId(), title, start: selectInfo.startStr, end: selectInfo.endStr, allDay: selectInfo.allDay }) } } handleEventClick = (clickInfo) => { if (window.confirm(`Are you sure you want to delete the event '${clickInfo.event.title}'`)) { clickInfo.event.remove() } } handleEvents = (events) => { // Ocultar el LOGO de producto no registrado var logo = document.getElementsByClassName('fc-license-message'); // console.log("Valor de 'logo': ",logo); // console.log("Evento : ",events); if ( logo.length === 1 ) { logo[0].style.visibility = 'hidden'; // Especial Hide logo } this.setState({ currentEvents: events }) } handlePrint = () => { window.print() } } function renderEventContent(eventInfo) { return ( <> <b>{eventInfo.timeText}</b> <i>{eventInfo.event.title}</i> </> ) } function renderSidebarEvent(event) { return ( <li key={event.id}> <b>{formatDate(event.start, {year: 'numeric', month: 'short', day: 'numeric'})}</b> <i>{event.title}</i> </li> ) }
Como siembre, os dejo los fuentes para que los podáis instalar en vuestros equipos.
Adjuntos
Archivo | Tamaño de archivo | Descargas |
---|---|---|
![]() |
183 KB | 28 |
![]() |
178 KB | 24 |