Fullcalendar+reactで外部のイベントをドラッグ&ドロップしている記事が見つけられなかったので書いてみました。
構成
- react+typescript
- MUI
- Fullcalendar
reactにFullcalendarの導入
ここら辺は飛ばしますので下記を参考にしてください。
基本のカレンダー
index.ts
import React from 'react';
// FullCalendar
import FullCalendar from '@fullcalendar/react';
import timeGridPlugin from '@fullcalendar/timegrid';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import jaLocale from '@fullcalendar/core/locales/ja';
import listPlugin from '@fullcalendar/list';
import { Grid } from '@mui/material';
const SampleCalendar: React.FC = () => {
const ref = React.createRef<any>();
return (
<Grid container>
<FullCalendar
ref={ref}
locales={[jaLocale]}
plugins={[timeGridPlugin, dayGridPlugin, interactionPlugin, listPlugin]}
initialView='dayGridMonth'
slotDuration='00:30:00'
headerToolbar={{
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek',
}}
//
selectable={true}
weekends={true}
/>
</Grid>
);
};
export default SampleCalendar;
外部イベントdrop可能にする
droppableをtrueにすることで、内部外部に関わらずイベントのdropが可能になります。
外部イベントをdropした時に発火するdropに指定します。
eventDropと間違えないように注意してください。
こちらは内部のイベントをdropした時に発火します。
index.ts
const drop=()=>{
console.log('dropした')
}
<FullCalendar
// 省略
+ droppable={true}
+ drop={drop}
/>
外部イベントコンポーネント作成
dropができるだけのシンプルな外部イベントを作成します。
components/ExternalEvents.tsx
import React, { useEffect, useRef } from "react";
import { Draggable } from "@fullcalendar/interaction";
import { Box } from "@mui/material";
type Props = {
event: { id: number; title: string };
};
export const ExternalEvent = ({ event }: Props) => {
const elRef = useRef<HTMLButtonElement | null>(null);
useEffect(() => {
if (!elRef.current) return;
const draggable = new Draggable(elRef.current, {
eventData: () => {
return { ...event, create: true };
},
});
return () => draggable.destroy();
});
return (
<Box
component="div"
ref={elRef}
title={event.title}
sx={{
fontWeight: "bold",
cursor: "grab",
mb: "0.6rem",
mx: "1.5rem",
}}
>
{event.title}
</Box>
);
};
外部イベントを反映
これで完成です。
index.ts
import React from 'react';
// FullCalendar
import React from "react";
// FullCalendar
import FullCalendar from "@fullcalendar/react";
import timeGridPlugin from "@fullcalendar/timegrid";
import dayGridPlugin from "@fullcalendar/daygrid";
import interactionPlugin from "@fullcalendar/interaction";
import jaLocale from "@fullcalendar/core/locales/ja";
import listPlugin from "@fullcalendar/list";
import { Grid } from "@mui/material";
import { ExternalEvent } from "@/conponents/externalEvents";
const events = [
{
id: "1",
title: "脚トレ",
},
{
id: "2",
title: "胸トレ",
},
{
id: "3",
title: "背中トレ",
},
];
const SampleCalendar: React.FC = () => {
const ref = React.createRef<any>();
const drop = () => {
console.log("dropした");
};
return (
<Grid container>
<Grid item xs={3}>
{events.map((event) => (
<ExternalEvent event={event} key={event.id} />
))}
</Grid>
<Grid item xs={9}>
<FullCalendar
ref={ref}
locales={[jaLocale]}
plugins={[
timeGridPlugin,
dayGridPlugin,
interactionPlugin,
listPlugin,
]}
initialView="dayGridMonth"
slotDuration="00:30:00"
headerToolbar={{
left: "prev,next today",
center: "title",
right: "dayGridMonth,timeGridWeek",
}}
//
selectable={true}
weekends={true}
droppable={true}
drop={drop}
/>
</Grid>
</Grid>
);
};
export default SampleCalendar;