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 |
|---|---|---|
fullcalendar-react
|
183 KB | 298 |
scheduler-react
|
178 KB | 286 |