Laravel中如何获取FullCalendar事件ID以实现事件删除
Laravel + FullCalendar 日历应用删除事件模态框问题
问题描述
我正在开发基于Laravel和FullCalendar的日历应用,需要实现点击日历事件弹出带删除按钮的模态框来删除事件。目前可以通过JS选择器获取事件ID并以文本展示,但无法将其转为PHP变量用于表单的action参数。
我采用异步加载事件的方式(而非通过foreach循环填充FullCalendar的events数组),原因是后者会让页面源代码充斥大量事件信息,而异步加载能提升页面渲染速度(可能我的理解存在偏差)。
现有代码实现
EventsController
public function getEvents() { return Event::where('event_date', '>', '2022-01-01') ->join('hospitals', 'events.hospital_id', '=', 'hospitals.hospital_id') ->select('hospitals.hospital_color', 'hospitals.hospital_max_people', 'event_id', 'event_content', 'event_date', 'user_id') ->get() ->map(fn ($events) => [ 'id' => $events->event_id, 'title' => $events->event_content, 'start' => $events->event_date, 'allDay' => true, 'editable' => false, 'backgroundColor' => $events->hospital_color, 'borderColor' => $events->hospital_color, 'hospital_max_people' => $events->hospital_max_people, 'volunteer' => User::find($events->user_id)->first_name .' '. User::find($events->user_id)->last_name ]); }
Events Blade模板 - FullCalendar设置
<script> document.addEventListener('DOMContentLoaded', function() { var calendarEl = document.getElementById('calendar'); var calendar = new FullCalendar.Calendar(calendarEl, { editable: false, droppable: true, selectable: true, initialView: 'dayGridWeek', views: { dayGridWeek: { type: 'dayGridWeek', duration: { weeks: 2 }, buttonText: '4 day' } }, header: { left: 'prev,next today', center: 'title', right: 'month,listMonth' }, themeSystem: 'bootstrap5', locale: 'en', firstDay: '1', contentHeight: 500, height: 700, expandRows: true, events: 'getEvents', eventClick: function(calendar, jsEvent, view) { $('#eventDetail').modal("show"); $('#id').html(calendar.event.id); $('#title').html(calendar.event.title); $('#start').html(moment(calendar.event.start).format('DD.MM.YYYY')); $('#volunteer').html(calendar.event.extendedProps.volunteer); } }); calendar.render(); }); </script>
Events Blade模板 - 模态框代码
<div class="modal fade" id="eventDetail" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="bar" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="staticBackdropLabel">Event details</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> Start: <p id="start"></p> Volunteer: <p id="volunteer"></p> Title: <p id="title"></p> </div> <div class="modal-footer"> <form method="POST" action="{{ route('calendar.destroy') }}" class="needs-validation" novalidate=""> @csrf @method('DELETE') <div class="form-group"> <x-button tabindex="3"> {{ __('Delete event') }} </x-button> </div> </form> </div> </div> </div> </div>
解决方案
方法1:通过隐藏字段传递事件ID
这是最直接的实现方式,把事件ID存入隐藏表单字段,提交时一起传给后端:
- 在模态框的表单中添加隐藏input:
<form method="POST" action="{{ route('calendar.destroy') }}" class="needs-validation" novalidate=""> @csrf @method('DELETE') <!-- 添加隐藏字段存储事件ID --> <input type="hidden" name="event_id" id="event_id"> <div class="form-group"> <x-button tabindex="3"> {{ __('Delete event') }} </x-button> </div> </form>
- 在
eventClick回调中给隐藏字段赋值:
eventClick: function(info) { $('#eventDetail').modal("show"); $('#id').html(info.event.id); $('#title').html(info.event.title); $('#start').html(moment(info.event.start).format('DD.MM.YYYY')); $('#volunteer').html(info.event.extendedProps.volunteer); // 给隐藏字段设置当前事件ID $('#event_id').val(info.event.id); }
- 后端
destroy方法接收并处理:
public function destroy(Request $request) { $event = Event::findOrFail($request->event_id); $event->delete(); return redirect()->back()->with('success', '事件已删除'); }
方法2:动态修改表单action(RESTful路由场景)
如果你的路由是RESTful风格(比如/calendar/{event}),可以动态替换action中的ID参数:
- 调整路由定义:
Route::delete('/calendar/{event}', [EventsController::class, 'destroy'])->name('calendar.destroy');
- 修改模态框表单,去掉固定action:
<form method="POST" class="needs-validation" novalidate=""> @csrf @method('DELETE') <div class="form-group"> <x-button tabindex="3"> {{ __('Delete event') }} </x-button> </div> </form>
- 在
eventClick中动态设置表单action:
eventClick: function(info) { $('#eventDetail').modal("show"); // 其他渲染代码... // 替换路由模板中的ID占位符 const deleteUrl = "{{ route('calendar.destroy', ['event' => ':id']) }}".replace(':id', info.event.id); $('#eventDetail form').attr('action', deleteUrl); }
- 后端使用路由模型绑定直接获取事件:
public function destroy(Event $event) { $event->delete(); return redirect()->back()->with('success', '事件已删除'); }
补充说明
- 你对异步加载事件的理解是正确的:这种方式能减少初始页面的HTML体积,提升首屏渲染速度,事件数量越多优势越明显。
- FullCalendar官方文档中,
eventClick的回调参数是info对象,建议把原代码中的参数名从calendar改成info,避免和日历实例混淆。
内容的提问来源于stack exchange,提问作者Nikola
相关产品推荐
相关产品推荐

