我使用fullcalendar v4来显示事件。 事件在负载中正常显示,但是我需要使用多个复选框添加过滤器,并在使用ajax的onchange复选框之后刷新全日历事件。
更改后,我得到了新的对象事件,但是我需要刷新fullcalendar
我尝试使用calendar.render();
,但无法正常工作
fullcalendar V4 !!
全日历脚本
var taskEvents = JSON.parse($("input[name=tasks_events]").val());
var calendarEl = document.getElementById('tasks_calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
locale: 'fr',
plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek'
},
defaultDate: new Date(),
defaultView: 'timeGridWeek',
minTime: "09:00:00",
maxTime: "20:00:00",
weekends:false,
businessHours: true, // display business hours
editable: true,
selectable: true,
droppable: true,
//events:taskEvents ,
select: function(info) {
$('#newTaskFormLabel').html('Commence à '+"<b> " + moment(info.startStr).format('DD-MM-YYYY HH:mm') + "</b> "+" fin à " +"<b> " + moment(info.endStr).format('DD-MM-YYYY HH:m:m')) +"</b>"
$('#newTaskForm').modal('show');
$('#newTaskForm input[name=start_at]').val(info.startStr);
$('#newTaskForm input[name=end_at]').val(info.endStr);
},
eventClick: function(info) {
$('#editTaskForm').modal('show');
console.log(info);
editTask(info.event);
},
// dateClick: function(info) {
// alert('clicked ' + info.dateStr);
// },
eventResize: function(info) {
$('.popover.in').remove();
if (confirm("Êtes-vous sûr de vouloir appliquer ces modifications?")) {
submitTimeChanges(info.event);
}else{
info.revert();
}
},
eventDrop : function(info){
$('.popover.in').remove();
// $(info.el).removeAttr('aria-describedby');
if (confirm("Êtes-vous sûr de vouloir appliquer ces modifications?")) {
submitTimeChanges(info.event);
}else{
info.revert();
}
},
eventRender: function(info) {
$(info.el).append('<img src="'+document.location.origin+'/'+info.event.extendedProps.user_avatar+'" class="img-circle event-avatar" alt="User Image">');
let state = function (state) {
if(state =="not_started") return "Pas encore commencé";
if(state =="started") return "Commencé";
if(state =="finish") return "Terminer";
}
$(info.el).popover({
title: info.event.title,
content: function () {
let html ="<p>"+moment(info.event.start).format('DD-MM-YYYY HH:mm')+' / '+moment(info.event.end).format('DD-MM-YYYY HH:mm')+"</P>"
+"<p>"+info.event.extendedProps.description+"</p>"
+"<p>"+"Utilisateur : "+info.event.extendedProps.user+"</p>"
+"<p>"+"Projet : "+info.event.extendedProps.project+"</p>"
+"<p>"+"Fonction : "+info.event.extendedProps.activity+"</p>"
+"<a class='btn btn-primary btn-xs'>"+state(info.event.extendedProps.state)+"</a>";
return html;
},
trigger: 'hover',
placement: 'top',
html: 'true',
container: 'body'
});
},
});
calendar.addEventSource( taskEvents );
calendar.render();
//--------------------------------------------------------
ajax脚本
var getTasks = function (data){
$.ajax({
url:"/admin/get-users-tasks",
type:"POST",
data :{
users:data,
},
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
success: function (response) {
calendar.addEventSource( response );
calendar.refetchEvents();
},
error: function(response) {
new PNotify({
title: "Opération échoué",
text: response.message,
type: "error"
});
}
});
}
更改复选框功能
function onChangeUserCheckbox() {
$("input[name*=selected_user]").on('change',function () {
var selectedUsers = [];
$.each($("input[name*='selected_user']:checked"), function(){
selectedUsers.push($(this).val());
});
getTasks(selectedUsers);
// getTasks(JSON.stringify(selectedUsers));
})
}
答案 0 :(得分:1)
您还没有确切解释代码出了什么问题,但是我可以看到,当您从AJAX调用中获得响应时,每次都会添加一个新的事件源。我还可以看到,尽管您从未删除任何先前的事件源,所以您将继续获得越来越多的事件。我将假设这是您要问的问题。
但是,与其始终添加/删除事件源,不如将其声明为可以刷新和更新的单个事件源会更简单。您可以使用here in the documentation中所述的“事件作为功能”模式来声明此源。
下面是一些经过修改的代码,这些代码会更有意义:
var calendarEl = document.getElementById('tasks_calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
eventSources: [
JSON.parse($("input[name=tasks_events]").val()), //static event source
getTasks //pass a reference to a function, so we have a dynamic, updateable event source
]
///....all your other options go here as well....
});
$("input[name*=selected_user]").on('change',function () {
calendar.refetchEvents(); //this will automatically cause the "getTasks" function to run, because it's associated with an event source in the calendar
});
var getTasks = function(fetchInfo, successCallback, failureCallback) { //the input parameters are the ones shown in the fullCalendar documentation
//find the currently selected users
var selectedUsers = [];
$.each($("input[name*='selected_user']:checked"), function(){
selectedUsers.push($(this).val());
});
//run the ajax call
$.ajax({
url: "/admin/get-users-tasks",
type: "POST",
data: {
users: selectedUsers,
},
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
success: function (response) {
successCallback(response); //pass the event data to fullCalendar via the provided callback function
},
error: function(response) {
new PNotify({
title: "Opération échoué",
text: response.message,
type: "error"
});
failureCallback(response); //inform fullCalendar of the error via the provided callback function
}
});
}
一些注意事项:
1)在此版本中,当日历加载时,它将立即向服务器发出AJAX请求并尝试获取事件。但是,由于未选中任何复选框,因此不会将任何数据传递到服务器。在这种情况下,我不知道您的服务器代码目前正在做什么,或者您想要它做什么。我猜它应该返回所有可能的事件,或者根本不返回。无论哪种方式,您都需要确保已设置服务器代码来处理这种情况并返回有意义的数据。
2)我也在这里添加了其他事件集(从隐藏字段中获取)作为事件源。无需通过“ addEventSource”单独添加它,因为您可以在日历加载后立即添加它-您只需在选项中声明即可。
3)我没有在这里使用提供的fetchInfo
数据,但是理想情况下,您应该从该对象获取开始和结束日期值,并将其作为参数发送到服务器,并且您的服务器应该使用它们过滤数据并仅返回开始日期介于这两个日期之间的事件。这样会更有效率,因为这样一来,您将只返回实际上将在日历上显示的数据,而不是返回用户曾经执行过的所有任务-如果您考虑过,一旦您的应用程序已用于几个月后,它们将开始拥有大量过去的数据,每次下载都没有意义,因为几乎可以肯定不会看到。 (请注意,如果用户确实导航到过去/将来的日期,而fullCalendar没有这些日期的事件数据,它将再次运行AJAX调用并要求服务器提供该日期。但是,如果用户从不查看这些日期,它不会打扰,并且可以节省一些带宽和处理时间。)
有关在日历选项中配置事件源的文档,请参见https://fullcalendar.io/docs/eventSources。
答案 1 :(得分:0)
我的工作:销毁日历并重新渲染
不按照文档中的说明加载日历,而是:
function LoadCalendar() {
if (typeof calendar != "undefined") {
document.getElementById("calendar").innerHTML = "";
}
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
//... parameters
});
calendar.render();
}
然后在加载时:
function FirstCalendar() {
MesEvents = "$events"; // Ajax script is executed and give $events
LoadCalendar();
}
document.addEventListener('DOMContentLoaded', FirstCalendar);
最后,要进行Ajax更新:
function makeRequest(event) {
//... ajax instructions
httpRequest.onreadystatechange = function() { changeContents(httpRequest); };
httpRequest.open('POST', 'url/ajax.php', true);
httpRequest.send(oData);
}
function changeContents(httpRequest) {
try {
if (httpRequest.readyState == XMLHttpRequest.DONE) {
if (httpRequest.status == 200) {
reponse = JSON.parse(httpRequest.responseText);
MesEvents = JSON.parse(reponse.Events);
LoadCalendar();
} else {
alert('Un problème est survenu avec la requête : ' + httpRequest.status);
}
}
}
catch( e ) {
alert(\"Une exception s’est produite (changeContents) : \" + e.description);
}
}
答案 2 :(得分:0)
完整日历v4
首先,我要感谢ADyson和Boutamente的回答。它帮助我找到了解决方案。我的代码如下:
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'dayGrid','interaction','googleCalendar' ],
editable: true,
selectable: true,
dateClick: function(info) {
// open a modal form and submit using ajax
},
// eventClick is not required if you are using eventRender with bootstrap tooltip or popover. However it is up to you.
// eventClick: function(info) {
// alert('Event: '+titleCase(info.event.title)+'\n'+'Start: '+info.event.start.toDateString()+' '+info.event.start.toLocaleTimeString()+'\n'+'End: '+info.event.end.toDateString()+' '+info.event.end.toLocaleTimeString());
// },
// there is no need to set a static event source if you are
// fetching events using custom function
// eventSources allow you to fetch events using fn,json,array
eventSources: [
{
// FullCalendar will call this function whenever it needs new data
// fetchInfo is auto populated with start and end dates of calendar
// I manipulate the start and end data in my controller to search the db
// for more info on fetchInfo Object, https://fullcalendar.io/docs/events-function
// base_url() is a custom function
events:function(fetchInfo, successCallback, failureCallback) {
$.ajax({
type:'GET',
url: base_url() + "/fetchInfo",
data:{"start":fetchInfo.start.toDateString(),"end":fetchInfo.end.toDateString()},
success: function(response) {
successCallback(response.dates.map(function(event) {
return {
id:event.id,
title:event.title,
start:event.start,
end:event.end,
}
})
);
},
error: function(response){
console.log(response);
failureCallback(response);
},
});
},
color: 'yellow',
}
],
eventDrop: function(info) {
if(!confirm("Are you sure about this change?")) {
info.revert();
}
// call function to update event date with ajax
modifyEvent(info.event);
},
eventRender: function(info) {
$(info.el).popover(
{
title:titleCase(info.event.title),
content:multiline('Start: ' + info.event.start.toDateString() + ' ' + info.event.start.toLocaleTimeString() + '\n' + 'End: ' + info.event.end.toDateString() + ' ' + info.event.end.toLocaleTimeString()),
html:true,
trigger:'hover',
container:'body',
placement:'top',
});
},
});
// refetch events once you close the modal form
$('#createEventModal').on('hidden.bs.modal', function() {
calendar.refetchEvents();
});
calendar.render();
});
</script>
答案 3 :(得分:-1)
请检查以下代码:
$.ajax({
url:"/admin/get-users-tasks/"+data,
type:"GET",
success: function (response) {
calendar.addEventSource( '/admin/get-users-tasks/'+data );
var eventSource = calendar.getEventSources();
eventSource[0].remove();
eventSource[0].refetch();
},
error: function(response) {
new PNotify({
title: "Opération échoué",
text: response.message,
type: "error"
});
}
});