[英]Problems on events update and creation on fullcalendar (rendering events infos and multiple events)
我在 laravel 应用程序 (8.75) 上使用带 livewire 的 fullcalendar JS (6.0.1)。 我有一个包含一些事件的日历。
当我单击事件时,会打开一个模态 window,其中包含一个填写了标题、描述、开始日期和全天输入等信息的表单。 输入已启用,我可以使用提交按钮更新事件或使用另一个按钮将其删除。
更新和删除功能有效。
当我点击某一天时,相同的模态 window 打开时会显示一个空表单(当然不会出现删除按钮)。 我可以通过提交此表单来创建一个活动,它有效
我的问题是,在创建或更新之后,模态关闭,我返回到日历。 我的新事件(或我所做的修改)出现在它(时间和标题)上,但如果我单击它以查看详细信息,模态上的表单对于事件创建是空的(没有标题、描述、开始日期等)ans 空的数据我刚刚更改了更新。如果我单击日历上的任何其他事件(以前创建的事件)也是一样的。 我必须刷新页面才能在单击它时查看详细信息。
当我在 eventClick() 上记录 info.event 时,即使我只是更改了某些内容,我也拥有所有正确的事件数据。 日历上显示的数据也是正确的。
因此,我认为这是由于我的模态表单填充功能所致,但我无法确定。
这是我的 livewire 组件:
<div>
<div>
<div id='calendar-container' wire:ignore>
<div id='calendar' class="z-10"></div>
</div>
</div>
@push('scripts')
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.js'></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/locales-all.min.js"></script>
<script>
document.addEventListener('livewire:load', function () {
const Calendar = FullCalendar.Calendar;
const calendarEl = document.getElementById('calendar');
const calendar = new Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
locale: '{{config('app.locale')}}',
events: JSON.parse(@this.events),
editable: true,
eventResize: info => @this.eventChange(info.event),
eventDrop: info => @this.eventChange(info.event),
selectable: true,
unselectAuto: true,
longPressDelay: 1,
eventLongPressDelay: 1,
selectLongPressDelay: 1,
select: arg => {
arg.jsEvent.preventDefault();
// Select the modal
let modal = document.getElementById('modal')
// Empty inputs
modal.querySelectorAll('input').forEach((el) => {
el.setAttribute('value', '')
})
// Unselect checkbox
modal.querySelector('input[id="allDay"]').removeAttribute('checked')
// If deletion button is present, hide it
let deleteBtn = modal.querySelector('#delete')
if(!deleteBtn.hasAttribute('hidden')) {
deleteBtn.setAttribute('hidden', true)
}
// Fill the start date with the selected date
modal.querySelector('input[id="start"]').setAttribute('value', (new Date((arg.start).toString().split('GMT')[0]+' UTC').toISOString()).substr(0,23))
// Change modal title
modal.querySelector('#modal-title').innerText = 'Create an event'
// If modal is hidden
if(modal.hasAttribute('hidden')) {
// Display it
modal.removeAttribute('hidden')
}
// On submitting form
modal.querySelector('button[id="submitCreatingEventForm"]').addEventListener('click', (evt) => {
evt.preventDefault()
// evt.stopImmediatePropagation()
if(title && start) {
// allDay definition
let allD = allDay.checked ? true : false
// Adding event on db
@this.eventAdd({
title: title.value,
description: description.value,
start: start.value,
end: end.value,
allDay: allD
});
// Adding event on calendar
calendar.addEvent({
title: title.value,
description: description.value,
start: start.value,
end: end.value,
allDay: allD
});
}
})
// @this.render()
// Close modal button
document.getElementById('close').addEventListener('click', (evt) => {
document.getElementById('modal').setAttribute('hidden', true)
@this.render()
// Unselect the selection
calendar.unselect();
})
// Unselect the selection
calendar.unselect();
calendar.render();
},
eventClick: info => {
info.jsEvent.preventDefault();
console.log(info.event);
// Select the modal
let modal = document.getElementById('modal')
// Empty inputs
modal.querySelectorAll('input').forEach((el) => {
el.setAttribute('value', '')
})
// Unselect checkbox
modal.querySelector('input[id="allDay"]').removeAttribute('checked')
let deleteBtn = modal.querySelector('#delete')
// If deletion button is hidden
if(deleteBtn.hasAttribute('hidden')) {
// Display it
deleteBtn.removeAttribute('hidden')
}
// If a report has already been create, disabled the deletion button
if(info.event.extendedProps.report) {
deleteBtn.setAttribute('disabled', '')
} else {
deleteBtn.removeAttribute('disabled')
}
// deletion button
deleteBtn.addEventListener('click', (evt) => {
evt.preventDefault()
// Remove event form db
@this.eventRemove(info.event.id)
// remove event from calendar
info.event.remove()
})
// Modify modal title
modal.querySelector('#modal-title').innerText = 'Update an event'
// If modal is hidden
if(modal.hasAttribute('hidden')) {
// Display it
modal.removeAttribute('hidden')
}
// Fill the form inputs
// Title
modal.querySelector('input[id="title"]').setAttribute('value', info.event.title)
// Description
if(info.event.extendedProps.description != null) {
modal.querySelector('input[id="description"]').setAttribute('value', info.event.extendedProps.description)
}
// Start date
modal.querySelector('input[id="start"]').setAttribute('value', (new Date((info.event.start).toString().split('GMT')[0]+' UTC').toISOString()).substr(0,23))
// allDay
if(info.event.allDay) {
modal.querySelector('input[id="allDay"]').setAttribute('checked', true)
}
// On form submitting
modal.querySelector('button[id="submitCreatingEventForm"]').addEventListener('click', (evt) => {
evt.preventDefault()
const e = info.event
if(title && start) {
// Modify calendar event object
if(title.value != e.title) {
e.setProp('title', title.value)
}
if(description.value != e.extendedProps.description) {
e.setExtendedProp( 'description', description.value )
}
if(start.value != (new Date((e.start).toString().split('GMT')[0]+' UTC').toISOString()).substr(0,23)) {
e.setStart(start.value)
}
if(allDay.checked != e.allDay) {
e.setAllDay(allDay.checked)
}
// Modify db event
@this.eventUpdate({
id: e.id,
title: title.value,
description: description.value,
start: start.value,
end: end.value,
allDay: allDay.checked
});
@this.render()
}
// deletion button
modal.querySelector('button[id="delete"]').addEventListener('click', (evt) => {
// Remove event on calendar
calendar.remove(e)
// Remove event on db
$this.eventRemove(e.id)
})
})
// close modal button
document.getElementById('close').addEventListener('click', (evt) => {
document.getElementById('modal').setAttribute('hidden', true)
calendar.render()
})
}
});
calendar.render();
});
</script>
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.css' rel='stylesheet' />
@endpush
<div id="modal" hidden>
<div>
<form>
<div>
<h1 id="modal-title">Créer un événement</h1>
<button id="submitCreatingEventForm" type="submit" >Enregistrer</button>
</div>
<div>
<div>
<label for="title">
Titre *
</label>
<input id="title" type="text">
</div>
</div>
<div>
<div>
<label for="description">
Description
</label>
<input id="description" type="text">
</div>
</div>
<div>
<div>
<label for="start">
Début *
</label>
<input id="start" type="datetime-local" name="start">
</div>
<div>
<label for="allDay">Journée entière</label>
<input id="allDay" type="checkbox" name="allDay" value="true">
</div>
<div hidden>
<label for="end">
Fin
</label>
<input id="end" type="datetime-local" name="end">
</div>
</div>
</form>
<div id="modal-buttons">
<button id="close">Fermer</button>
<button id="delete">Supprimer</button>
</div>
</div>
</div>
</div>
您是否看到任何可能导致此问题的原因?
这是我的日历组件:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Event;
use App\Models\Client;
use Illuminate\Support\Arr;
class Calendar extends Component
{
public $events = [];
public function mount($events)
{
$this->events = json_encode($events);
}
public function render()
{
return view('livewire.calendar');
}
public function eventChange($event)
{
$e = Event::find($event['id']);
$e->start = $event['start'];
if(Arr::exists($event, 'end')) {
$e->end = $event['end'];
}
$e->save();
}
public function eventAdd($event)
{
Event::create($event);
}
public function eventRemove($id)
{
Event::destroy($id);
}
public function eventUpdate($event)
{
$e = Event::find($event['id']);
$e->title = $event['title'];
$e->description = $event['description'];
$e->start = $event['start'];
$e->end = $event['end'];
$e->allDay = $event['allDay'];
if($e->isDirty()) {
$e->update($event);
}
}
public function reload() {
return redirect(request()->header('Referer'));
}
}
尽管我进行了研究,但我仍然找不到解决方案。
有人知道吗?
通过在调用 select 和 eventClick 方法的每个侦听器上使用 removeEventListener() 并在我的回调函数顶部添加 evt.stopImmediatePropagation() 以提交 forms(用于创建和更新),我不再有多个创建。
为了完成并避免在 select 和 eventClick 方法上调用不必要的事件侦听器,我分解了侦听器以关闭日历 object 之外的模式(因为此 function 上没有任何内容使用日历属性)
select: arg => {
[...]
let submitCreationBtn = modal.querySelector('button[id="submitCreatingEventForm"]')
submitCreationBtn.addEventListener('click', handleSubmitCreationForm)
function handleSubmitCreationForm(evt) {
evt.preventDefault()
evt.stopImmediatePropagation()
if(title && start) {
let allD = allDay.checked ? true : false
@this.eventAdd({
title: title.value,
description: description.value,
start: start.value,
end: end.value,
allDay: allD
});
calendar.addEvent({
title: title.value,
description: description.value,
start: start.value,
end: end.value,
allDay: allD
});
}
submitCreationBtn.removeEventListener('click', handleSubmitCreationForm)
}
[...]
}
eventClick: info => {
[...]
let submitUpdateBtn = modal.querySelector('button[id="submitCreatingEventForm"]')
submitUpdateBtn.addEventListener('click', handleSubmitUpdateForm)
function handleSubmitUpdateForm(evt) {
evt.preventDefault()
evt.stopImmediatePropagation()
const e = info.event
if(title && start) {
if(title.value != e.title) {
e.setProp('title', title.value)
}
if(description.value != e.extendedProps.description) {
e.setExtendedProp( 'description', description.value )
}
if(start.value != (new Date((e.start).toString().split('GMT')[0]+' UTC').toISOString()).substr(0,23)) {
e.setStart(start.value)
}
if(allDay.checked != e.allDay) {
e.setAllDay(allDay.checked)
}
@this.eventUpdate({
id: e.id,
title: title.value,
description: description.value,
start: start.value,
end: end.value,
allDay: allDay.checked
});
@this.render()
}
submitUpdateBtn.removeEventListener('click', handleSubmitUpdateForm)
}
[...]
}
<script>
[...]
let closeBtn = document.getElementById('close')
closeBtn.addEventListener('click', handleClickOnCloseBtn)
function handleClickOnCloseBtn(evt) {
document.getElementById('modal').setAttribute('hidden', true)
}
[...]
</script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.