我在一个laravel应用程序(8.75)上使用fullcalendar JS(6.0.1)和livewire,我有一个日历,上面有一些事件。
当我点击事件时,一个模态窗口打开,其中有一个表单,填写了标题,描述,开始日期和输入的所有日期等信息。输入被启用,我可以使用提交按钮更新事件,或使用另一个按钮删除它。
更新和删除功能正常工作。
当我点击某一天,同样的模态窗口打开一个空的表单(和删除按钮不出现当然)。我可以创建一个事件提交此表单,它的工作
我的问题是,在创建或更新之后,模态被关闭,我返回到日历。(或我所做的修改)(时间和标题),但如果我单击它查看详细信息,模态上的表单对于事件创建是空的(没有标题,描述,开始日期等),而我刚刚更新的数据为空。如果我单击日历上的任何其他事件,也是如此(以前创建的事件)。单击该页面时,我必须刷新该页面才能查看详细信息。
当我在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'));
}
}
尽管我做了研究,我还是找不到解决办法。
有人知道这件事吗?
1条答案
按热度按时间wpx232ag1#
通过在调用select和eventClick方法的每个侦听器上使用removeEventListener(),并在回调函数的顶部添加evt. stopImmediatePropagation()以提交表单(用于创建和更新),我不再需要多次创建。
为了完成并避免在select和eventClick方法上调用不必要的eventlistener,我对侦听器进行了因子分解,以关闭calendar对象外部的模态(因为此函数没有使用calendar属性)