[英]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.