I'm developing an event Scheduler using fullCalendar resource library with draggable events. I was able to get the events being dragged get saved in the database.
For now, the database has only one table with three columns - id(autoincrement), title,start, end.
I've just added the resource column to the calendar which also has an add rooms button on it that lets the user add the rooms himself. Here's what I've referred to built it.
For the draggable events: https://fullcalendar.io/docs/external-dragging-demo
For the resources : https://fullcalendar.io/docs/addResource-demo
Here's my code:
main.js
document.addEventListener('DOMContentLoaded', function() {
var Calendar = FullCalendar.Calendar;
var Draggable = FullCalendarInteraction.Draggable;
var containerEl = document.getElementById('external-events');
var calendarEl = document.getElementById('calendar');
var checkbox = document.getElementById('drop-remove');
new Draggable(containerEl, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
return {
title: eventEl.innerText
};
}
});
var calendar = new Calendar(calendarEl, {
plugins: [ 'interaction', 'resourceTimeline' ],
header: {
left: 'promptResource today prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek'
},
customButtons: {
promptResource: {
text: '+ room',
click: function() {
var title = prompt('Room name');
console.log(title);
if (title) {
calendar.addResource({
title: title
});
fetch('add_resources.php', {
method: 'POST',
headers: {
'Accept': 'application/json'
},
body: encodeFormData(title)
})
.then(response => console.log(response))
.catch(error => console.log(error));
}
}
}
},
editable: true,
aspectRatio: 1.5,
defaultView: 'resourceTimelineDay',
resourceLabelText: 'Rooms',
resources: '',
events: '',
droppable: true,
drop: function(info) {
if (checkbox.checked) {
info.draggedEl.parentNode.removeChild(info.draggedEl);
}
},
eventLimit: true,
events: "all_events.php",
displayEventTime: false,
eventRender: function (event, element, view) {
if (event.allDay === 'true') {
event.allDay = true;
} else {
event.allDay = false;
}
},
selectable: true,
selectHelper: true,
eventReceive: function(info) {
var eventData = {
title: info.event.title,
start: moment(info.event.start).format("YYYY-MM-DD HH:mm"),
end: moment(info.event.start).format("YYYY-MM-DD HH:mm")
};
console.log(eventData);
//send the data via an AJAX POST request, and log any response which comes from the server
fetch('add_event.php', {
method: 'POST',
headers: {
'Accept': 'application/json'
},
body: encodeFormData(eventData)
})
.then(response => console.log(response))
.catch(error => console.log(error));
}
});
calendar.render();
});
const encodeFormData = (data) => {
var form_data = new FormData();
for ( var key in data ) {
form_data.append(key, data[key]);
}
return form_data;
}
index.php
<link href='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.css' rel='stylesheet' />
<link href='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.css' rel='stylesheet' />
<link href='https://unpkg.com/#fullcalendar/timegrid#4.4.0/main.min.css' rel='stylesheet' />
<script src='https://unpkg.com/#fullcalendar/core#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/interaction#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/daygrid#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/timegrid#4.4.0/main.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<link href='https://unpkg.com/#fullcalendar/timeline#4.4.0/main.min.css' rel='stylesheet' />
<link href='https://unpkg.com/#fullcalendar/resource-timeline#4.4.0/main.min.css' rel='stylesheet' />
<script src='https://unpkg.com/#fullcalendar/timeline#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/resource-common#4.4.0/main.min.js'></script>
<script src='https://unpkg.com/#fullcalendar/resource-timeline#4.4.0/main.min.js'></script>
<link href="main.css" rel="stylesheet">
<script src='main.js'></script>
<div id='external-events'>
<p>
<strong>Draggable Events</strong>
</p>
<div class='fc-event'>My Event 1</div>
<div class='fc-event'>My Event 2</div>
<div class='fc-event'>My Event 3</div>
<div class='fc-event'>My Event 4</div>
<div class='fc-event'>My Event 5</div>
<p>
<input type='checkbox' id='drop-remove' />
<label for='drop-remove'>remove after drop</label>
</p>
</div>
<div id='calendar-container'>
<div id='calendar'></div>
</div>
add_resouces.php
<?php
require 'connection.php';
$title = $_POST['title'];
$conn = DB::databaseConnection();
$conn->beginTransaction();
$sqlInsert = "INSERT INTO Resources ( resourceTitle ) VALUES ( :title )";
$stmt = $conn->prepare($sqlInsert);
$stmt->bindParam(':title', $title);
if ($stmt->execute()) {
$conn->commit();
return true;
} else {
$conn->rollback();
return false;
}
?>
So I'm making another table for the resources with two columns in it - roomId and roomTitle. My question is how do I save the roomTitle into the database using the '+ room' button.
For now, the frontend for the resource column is working - i.e the room is visible on the page after I add it through that button. The event drag and drop is working too - it is getting saved to the database after being dropped on the calendar.
You need to add an AJAX request after your command to add the resource to the calendar, so that you send the title data to add_resources.php.
customButtons: {
promptResource: {
text: "+ room",
click: function() {
var title = prompt("Room name");
if (title) {
calendar.addResource({
title: title
});
fetch("add_resources.php", {
method: "POST",
headers: {
Accept: "application/json"
},
body: encodeFormData({ "title": title})
})
.then(response => console.log(response))
.catch(error => console.log(error));
}
}
}
},
Demo: https://codepen.io/ADyson82/pen/WNNeLNV?&editable=true&editors=001
Related
I am trying to incorporate context menu from https://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=menu&demo=contextMenu
using full calender io events and i am unable to understand how to plug in oj component under fullcalender io events.
I am aware that context menus can be accomplised using jquery ui context menu, but i want to know how to use jet code from fullcalendar io events.
Can you please let me know how i can plug in the jet context menu in the below code?
JET
require(['ojs/ojoffcanvas','knockout','ojs/ojbootstrap','ojs/ojarraydataprovider','jquery','ojs/ojknockout',
'fullCalendar','moment','jqueryui','jquerycontextmenu',
'ojs/ojknockout', 'ojs/ojdiagram','ojs/ojformlayout','ojs/ojbutton',
'ojs/ojmenu', 'ojs/ojoption','ojs/ojinputtext','ojs/ojselectcombobox'],
function (ko, Bootstrap,ArrayDataProvider,$) {
function ChartModel() {
var self = this;
self.addressBookData = ko.observableArray([]);
self.columns = ko.observableArray([
{ headerText : 'title', field : 'title'},
{ headerText : 'start', field : 'start'},
{ headerText : 'end', field : 'end'},
{ headerText : 'QuantityOrdered', field : 'QuantityOrdered'},
{ headerText : 'QuantityCompleted', field : 'QuantityCompleted'}
])
this.dataprovider = new ArrayDataProvider(self.addressBookData, { keyAttributes: 'title'});
}
function getE1Data(self,callback) {
var input = {
aliasNaming: true,
findOnEntry: "TRUE",
maxPageSize: "100",
targetName: "XXX",
aliasNaming : true,
targetType: "view",
dataServiceType: "BROWSE",
returnControlIDs: "TABLEX.DOCO|TABLEX.DL01|TABLEX.LITM|TABLEX.STRT|TABLEX.DRQJ|TABLEX.UORG|TABLEX.SOQS|TABLEX.SOCN|TABLEX.SRST"
};
callAISService(input, DATA_SERVICE, function(response) {
if (response.message) {
callback("failed");
} else {
renderData($,self,response.fs_DATABROWSE_V4801C.data.gridData.rowset);
callback("success");
}
});
}
function renderData($,self,data) {
self = this;
this.events = [];
data.forEach(element => {
const obj ={};
const extendedProps ={};
var teststr1 = (element.TABLEX_LITM.value).concat(" - ",(element.TABLEX_DOCO.value));
var teststr2 = (element.TABLEX_DL01.value).concat(" - ",teststr1);
obj.title = teststr2,
obj.start = new Date(element.TABLEX_DRQJ.value),
obj.end= new Date(element.TABLEX_STRT.value),
extendedProps.QuantityOrdered = element.TABLEX_UORG.value,
extendedProps.QuantityCompleted = element.TABLEX_SOQS.value,
extendedProps.QuantityScrapped = element.TABLEX_SOCN.value,
extendedProps.WOStatus = element.TABLEX_SRST.value,
obj.extendedProps = extendedProps,
events.push(obj);
});
this.calendar = $ ('#calendar').fullCalendar(
{
editable: true,
weekends : true,
selectable: true,
selectHelper:true,
timeFormat: 'H(:mm)',
displayEventTime: false,
header:{
left : 'prev,next,today',
center : 'title',
right : 'month,agendaWeek,agendaDay'
},
events: events,
eventClick: function(self,events) {
console.log(events.extendedProps.QuantityOrdered);
console.log(events.extendedProps.QuantityCompleted);
},
eventRender: function (events, element) {
element.attr('href', 'javascript:void(0);');
element.click(function() {
$("#startTime").html(formatDate(events.start));
$("#endTime").html(formatDate(events.end));
$("#QuantityOrdered").html(events.extendedProps.QuantityOrdered);
$("#QuantityCompleted").html(events.extendedProps.QuantityCompleted);
$("#QuantityScrapped").html(events.extendedProps.QuantityScrapped);
$("#WOStatus").html(events.extendedProps.WOStatus);
$("#eventContent").dialog({ modal: true, resizable: true ,effect: "explode",title: events.title, width:350});
});
}
});
}
$(document).ready(function() {
var chartModel = new ChartModel();
getE1Data(chartModel,(status)=>{
ko.applyBindings(chartModel, document.getElementById('calendar'));
});
});
});
JET
HTML
<body
<br />
<div class = "container">
<div id = "calendar"> </div>
</div>
</body>
HTML
Please find the below sample HTML, which used JET libraries like oj-menu using which context menu is acheived:
<body id="content">
<oj-input-text id="filter" class="oj-form-control-max-width-md" label-hint="Filter" label-edge="inside"
placeholder="Type to filter" on-raw-value-changed="[[handleValueChanged]]" value="{{filter}}" clear-icon="always">
</oj-input-text>
<oj-input-text id="filter1" class="oj-form-control-max-width-md" label-hint="Filter1" label-edge="inside"
placeholder="Type to filter" on-raw-value-changed="[[handleValueChanged1]]" value="{{filter1}}" clear-icon="always">
</oj-input-text>
<oj-input-text id="filter2" class="oj-form-control-max-width-md" label-hint="Filter1" label-edge="inside"
placeholder="Type to filter" on-raw-value-changed="[[handleValueChanged2]]" value="{{filter2}}" clear-icon="always">
</oj-input-text>
<oj-table id='table' aria-label='Departments Table'
data='[[dataprovider]]'
scroll-policy='loadMoreOnScroll'
columns-default.sortable='disabled'
columns='{{columns}}'
style='width:100%; height: 1000px;'>
<oj-menu id="ctxMenu" slot="contextMenu" aria-label="Match Edit">
<oj-option value="Action 1">Work Centre Details</oj-option>
<oj-option value="Action 12">Resource Units</oj-option>
<oj-option value="Action 13">Work Day Calendar</oj-option>
</oj-menu>
<div id="eventContent" title="Event Details">
<div id="eventInfo"></div>
</div>
</oj-table>
</body>
on a button click event (custom command in the grid), i would like the data to kendo window (loadcontentfrom) action and wondering if anyone can guide please?
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
#Html.Label("Summary")
#(Html.Kendo().Grid<Settings.Services.Models.DocumentTypeStatusList>()
.Name("EmpGrid")
.Columns(columns =>
{
columns.Bound(c => c.DocumentType.DocumentTypeDescription).Width(200);
columns.Bound(c => c.Status).Width(100);
columns.Command(c => c.Custom("ADD").IconClass("k-icon k-i-plus").Click("showDetails")).Width(100);
})
.HtmlAttributes(new { style = "height: 700px;" })
.Scrollable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(p => p.DocumentType.DocumentTypeId);
})
.Read(read => read.Action("GetAllDocumentsTypeStatus", "Home"))
.PageSize(20)
)
)
#(Html.Kendo().Window().Name("Details")
.Title("Add/Edit Document Type Setting")
.Visible(false)
.Modal(true)
.Draggable(true)
.Width(600)
.LoadContentFrom("ModifyDocumentTypeSettings", "Home")
.Actions(actions => actions.Close())
)
</div>
</div>
this is the javascript function that gets the value from the grid but how do i pass it to the kendo window function:
function showDetails(e) {
e.preventDefault();
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
var wnd = $("#Details").data("kendoWindow");
wnd.content(detailsTemplate(dataItem));
wnd.center().open();
}
This is resolved by refactoring the code as below (see this question for more information: how to set LoadContentFrom kendo window in run time):
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
$(document.body).append('<div id="Window"></div>');
$('#Window').kendoWindow({
title: "Add/Edit Document Type Setting",
modal: true,
resizable: false,
width: 400,
content: "/Home/ModifyDocumentTypeSettings/" + dataItem.id,
visible: false,
minHeight: 350,
animation: {
open: {
effects: "expandVertical",
duration: 1000
},
},
close: function () {
setTimeout(function () {
$('#Window').kendoWindow('destroy');
}, 200);
}
}).html('<img src="761.gif" />').data('kendoWindow').center().open();
This is resolved by refactoring the code as below (see this question for more information: how to set LoadContentFrom kendo window in run time):
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
$(document.body).append('<div id="Window"></div>');
$('#Window').kendoWindow({
title: "Add/Edit Document Type Setting",
modal: true,
resizable: false,
width: 400,
content: "/Home/ModifyDocumentTypeSettings/" + dataItem.id,
visible: false,
minHeight: 350,
animation: {
open: {
effects: "expandVertical",
duration: 1000
},
},
close: function () {
setTimeout(function () {
$('#Window').kendoWindow('destroy');
}, 200);
}
}).html('<img src="761.gif" />').data('kendoWindow').center().open();
I am trying to make a one page CRUD application using FullCalendar. Actually, I did. I'm just getting errors when I create events and then delete them. When my application is clicked on an existing event, it has to be deleted. But I get the error shown below.
Error
and it is my event object.
Event object
Would you help me figure out what the problem is?
The javascript code is like below:
var teacher_id = 2;
function addEventToDB(teacher_name,teacher_id,title,start,end,color){
axios.post('events', {
teacher_name: teacher_name,
user_id: teacher_id,
title: title,
start: start,
end: end,
color: color
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
function deleteEventFromDB (event_id,teacher_name) {
axios.delete('/events/'+ event_id)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
var eventType = 'Individual';
var eventTitle = 'Available for Individual';
var eventColor = 'orange';
$(function () {
// page is now ready, initialize the calendar...
$('#calendar').fullCalendar({
// put your options and callbacks here
themeSystem: 'bootstrap4',
defaultView: 'agendaWeek',
allDaySlot: false,
slotEventOverlap: false,
slotDuration: '00:30:00',
slotLabelInterval: "01:00",
scrollTime: '08:00:00',
events: 'events',
//defaultTimedEventDuration: '00:30:00',
footer: {
center: 'eventTypeButton'
},
customButtons: {
eventTypeButton: {
text: 'Event type Toggle Button (Group/Individual)',
click: function() {
if(eventType=='Individual') {
eventType = 'Group';
eventTitle = 'Available for Group';
eventColor = 'blue';
} else {
eventType = 'Individiual';
eventTitle = 'Available for Individual';
eventColor = 'orange';
}
}
}
},
dayClick: function (date, jsEvent, view) {
end = date.clone();
end = end.add(30,'minutes');
$('#calendar').fullCalendar('renderEvent', {
title: eventTitle,
teacher : teacher_id,
teacher_name: teacher_name,
start: date.format(),
end: end.format(),
allDay: false,
color: eventColor
});
var title = eventTitle;
var start = date.format();
var end = end.format();
var color = eventColor;
var teacher_name = "{{ Auth::user()->name }}";
addEventToDB(teacher_name,teacher_id,title, start, end, color);
},
eventClick: function(event, jsEvent, view) {
$('#calendar').fullCalendar( 'rerenderEvents' );
console.log(event.id);
deleteEventFromDB(event.id,event.teacher_name);
$('#calendar').fullCalendar('removeEvents',event.id);
$('#calendar').fullCalendar( 'rerenderEvents' );
},
})
});
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Dashboard</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">My calendar</div>
<div class="card-body">
<div id='calendar'></div>
</div>
</div>
</div>
</div>
</div>
I am adding server code (I am using Laravel 5.6):
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\AvailableTime;
use Illuminate\Contracts\Auth\Authenticatable;
class AvailableTimeController extends Controller
{
public function index(Authenticatable $user)
{
if($user->hasRole('admin') || $user->hasRole('superadmin')){
return AvailableTime::all();
} else if( $user->hasRole('teacher')) {
return AvailableTime::where('user_id',$user->id)->get();
}
}
public function show($id)
{
return AvailableTime::findOrFail($id);
}
public function update(Request $request, $id)
{
$AvailableTime = AvailableTime::findOrFail($id);
$AvailableTime->update($request->all());
return $AvailableTime;
}
public function store(Request $request)
{
$AvailableTime = AvailableTime::create($request->all());
return $AvailableTime;
}
public function destroy($id)
{
try {
$availableTime = AvailableTime::find($id);
$availableTime->delete();
return 'Deleted Successfully';
}
catch ( \Exception $e) {
return redirect()->route('show_calendar')->withErrors
'JSONError' => "Event can not be deleted"
]);
}
}
}
The problem is because your process for adding events is flawed - you're adding an event to the calendar without waiting for the server to send you a valid ID for it. So that event can never be deleted or updated in the server by clicking on it in the calendar. It has no relationship to the event recorded in the database.
You have to send the event data to the server first, get back the auto-generated ID in the response, and then record that as part of the event object you pass into the fullCalendar "renderEvent". If you don't do that, then if you try to update or delete that event, it has no ID which the server would recognise.
Thank you for your advice and I could develop a solution. In fact, the problem is a synchronization problem, and every time I click to create a new event and I click to delete it, all events are refetched and the problem is solved. I share the codes for solving below.
function addEventToDB(teacher_name,teacher_id,title,start,end,color){
axios.post('events', {
teacher_name: teacher_name,
user_id: teacher_id,
title: title,
start: start,
end: end,
color: color
})
.then(function (response) {
$('#calendar').fullCalendar( 'refetchEvents' );
console.log(response);
})
.catch(function (error) {
$('#calendar').fullCalendar( 'refetchEvents' );
console.log(error);
});
}
function deleteEventFromDB (event_id,teacher_name) {
axios.delete('/events/'+ event_id)
.then(function (response) {
$('#calendar').fullCalendar( 'refetchEvents' );
console.log(response);
})
.catch(function (error) {
$('#calendar').fullCalendar( 'refetchEvents' );
console.log(error);
});
}
var eventType = 'Individual';
var eventTitle = 'Available for Individual';
var eventColor = 'orange';
$(function () {
// page is now ready, initialize the calendar...
$('#calendar').fullCalendar({
// put your options and callbacks here
themeSystem: 'bootstrap4',
defaultView: 'agendaWeek',
allDaySlot: false,
slotEventOverlap: false,
slotDuration: '00:30:00',
slotLabelInterval: "01:00",
scrollTime: '08:00:00',
events: 'events',
//defaultTimedEventDuration: '00:30:00',
footer: {
center: 'eventTypeButton'
},
customButtons: {
eventTypeButton: {
text: 'Event type Toggle Button (Group/Individual)',
click: function() {
if(eventType=='Individual') {
eventType = 'Group';
eventTitle = 'Available for Group';
eventColor = 'blue';
} else {
eventType = 'Individiual';
eventTitle = 'Available for Individual';
eventColor = 'orange';
}
}
}
},
dayClick: function (date, jsEvent, view) {
var end = date.clone();
end = end.add(30,'minutes');
var title = eventTitle;
var start = date.format();
var endformat = end.format();
console.log(endformat);
var color = eventColor;
var teacher_name = "{{ Auth::user()->name }}";
addEventToDB(teacher_name,teacher_id,title, start, endformat, color);
$('#calendar').fullCalendar('renderEvent', {
title: eventTitle,
teacher : teacher_id,
teacher_name: teacher_name,
start: date.format(),
end: end.format(),
allDay: false,
color: eventColor
});
},
eventClick: function(event, jsEvent, view) {
$('#calendar').fullCalendar( 'rerenderEvents' );
console.log(event.id);
deleteEventFromDB(event.id,event.teacher_name);
$('#calendar').fullCalendar('removeEvents',event.id);
$('#calendar').fullCalendar( 'rerenderEvents' );
},
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Thank you again for anyone who is response
event object in eventClick() doesn't have id property, Change id as _id
eventClick: function(event, jsEvent, view) {
$('#calendar').fullCalendar( 'rerenderEvents' );
deleteEventFromDB(event._id,event.teacher_name);
$('#calendar').fullCalendar('removeEvents',event._id);
$('#calendar').fullCalendar( 'rerenderEvents' );
},
I have a MVC application and I'm trying to insert properties of objects. For that, I made a modal popup via jQuery dialog. I don't want it interfering with other actions that the user is doing, so I made an Ajax.BeginForm. I hoped that when I do the insert, it will close on return PartialView(), but it opens the popup View on full screen instead of closing the dialog. Also, it is important that the base view should be dynamic, so you can open the dialog on any page and not make a postback.
I've read the other similar issues and couldn't resolve my problem.
There are some similar issues, but none of them
Please, help me to achieve the proper function if possible. Code below:
JS:
<script>
$(document).ready(function () {
var url = "";
$("#dialog-alert").dialog({
title: 'Error encountered!',
autoOpen: false,
resizable: false,
width: 350,
show: { effect: 'drop', direction: "up" },
modal: true,
draggable: true
});
if ('#TempData["msg"]' != "") {
$("#dialog-alert").dialog('open');
}
$("#lnkServer").on("click", function (e) {
//e.preventDefault(); //use this or return false
url = $(this).attr('href');
$('#dialog-edit').dialog({ title: "Add a new Server" });
$("#dialog-edit").dialog('close');
$("#dialog-edit").dialog('open');
return false;
});
$("#lnkIssType").on("click", function (e) {
//e.preventDefault(); //use this or return false
url = $(this).attr('href');
$('#dialog-edit').dialog({ title: "Add a new Issue Type" });
$("#dialog-edit").dialog('close');
$("#dialog-edit").dialog('open');
return false;
});
$("#lnkUser").on("click", function (e) {
//e.preventDefault(); //use this or return false
url = $(this).attr('href');
$('#dialog-edit').dialog({ title: "Add a new User" });
$("#dialog-edit").dialog('close');
$("#dialog-edit").dialog('open');
return false;
});
$("#lnkDept").on("click", function (e) {
//e.preventDefault(); //use this or return false
url = $(this).attr('href');
$('#dialog-edit').dialog({ title: "Add a new Department" });
$("#dialog-edit").dialog('close');
$("#dialog-edit").dialog('open');
return false;
});
$("#dialog-edit").dialog({
autoOpen: false,
resizable: false,
width: 400,
show: { effect: 'drop', direction: "up" },
modal: true,
draggable: true,
open: function (event, ui) {
//$(".ui-dialog-titlebar-close").hide();
$(this).load(url);
}
//buttons: {
// "Cancel": function () {
// $(this).dialog("close");
// }
//}
});
});
function onSuccess() {
$("#dialog-edit").dialog('close');
}
</script>
Form:
<div id="container">
#using (Ajax.BeginForm("AddDept", new AjaxOptions { OnSuccess = "onSuccess" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div>
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.Department_Name)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Department_Name, htmlAttributes: new { #class = "form-control text-box single-line input-properties", placeholder = "Collections" })
</div>
<div class="editor-label">
#Html.ValidationMessageFor(model => model.Department_Name)
</div>
<input type="submit" value="Submit" class="btn btn-default btn-add-properties" />
</fieldset>
</div>
}
</div>
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddDept([Bind(Include = "Department_Name")] Department #dept)
{
try
{
if (ModelState.IsValid)
{
db.Departments.Add(#dept);
db.SaveChanges();
TempData["Msg"] = "Data has been saved successfully";
return PartialView();
//return Redirect(System.Web.HttpContext.Current.Request.UrlReferrer.PathAndQuery);
}
}
catch
{
TempData["Msg"] = "Probably the record already exists. If not, contact Georgi Georgiev, RA Dept.";
return PartialView();
}
return PartialView(#dept);
}
My problem was probably due to that my Ajax.BeginForm popup View relied on different ActionResult in the controller compared to the Background View's.
Anyway, it turns out that I couldn't achieve my functionality without having a POST through Ajax.
Here's what I did (in Layout view):
$("#dialog-edit").dialog({
autoOpen: false,
resizable: false,
width: 400,
show: { effect: 'drop', direction: "up" },
modal: true,
draggable: true,
open: function (event, ui) {
//$(".ui-dialog-titlebar-close").hide();
$(this).load(url);
},
buttons: [{
text: "Submit",
"class": "btn-add-properties",
click: function () {
var form = $('form', this);
$.post(form.prop('action'),
form.serialize(),
function (response) {
alert("success");
})
.fail(function () {
alert("error");
});
$("#dialog-edit").dialog('close');
}
}]
});
The ajax post is the function under the dialog button.
Thanks to another post here on StackOverflow, I added some code to my select: method that prevents users from adding an event on a date prior to NOW.
The downside is that when they click on the empty time slot, and the system then complains (an alert message), the attempted event remains. How do I get rid of it? Thanks!
Update: Here's my code:
select: function(start, end, jsEvent) {
var check = start._d.toJSON().slice(0,10),
today = new Date().toJSON().slice(0,10),
m = moment(),
url = "[redacted]",
result = {};
title = "Class",
eventData = {
title: title,
start: start,
end: start.clone().add(2, 'hour'),
durationEditable: false,
instructorid: 123,
locationid: 234
};
if(check < today) {
alert("Cannot create an event before today.");
$("#calendar").fullCalendar('removeEvents', function(eventObject) {
return true;
});
} else {
$.ajax({ type: "post", url: url, data: JSON.stringify(eventData), dataType: 'JSON', contentType: "application/json", success: function(result) {
if ( result.SUCCESS == true ) {
$('#calendar').fullCalendar('renderEvent', eventData, true);
$('#calendar').fullCalendar('unselect');
} else {
alert(result.MESSAGE);
}
}});
}
}
If you're using FullCalendar V2, you need to use the removeEvents method.
You can use it to delete events with a certain ID by calling it in this way:
$("#calendar").fullCalendar('removeEvents', 123); //replace 123 with reference to a real ID
If you want to use your own function that decides whether or not an event get's removed, you can call it this way:
$("#calendar").fullCalendar('removeEvents', function(eventObject) {
//return true if the event 'eventObject' needs to be removed, return false if it doesn't
});
FullCalendar has a removeEvent method that uses an id when you create the event.
Example Full Calendar v1:
var calendar = $('#calendar').fullCalendar({ ... stuff ... });
calendar.fullCalendar( 'addEventSource', {id:123, stuff:'stuff'});
// ... other calendar things here...
calendar.fullCalendar( 'removeEvent', 123);
Reference API v1
Example FullCalendar v2:
var calendar = $('#calendar').fullCalendar({ ... stuff ... });
calendar.fullCalendar( 'addEventSource', {id:123, stuff:'stuff'});
// ... other calendar things here...
calendar.fullCalendar( 'removeEvents', [123]);
Reference API v2
Version 4.3
calendar = new Calendar(calendarEl, {
plugins : [ 'interaction', 'dayGrid', 'list' ],
header : {
left : 'prev,next today',
center : 'title',
right : 'dayGridMonth,timeGridWeek,timeGridDay,list'
},
editable : true,
droppable : true,
eventReceive : function(info) {
alert(info.event.title);
},
eventDrop : function(info) {
alert(info.event.title + " was dropped on "
+ info.event.start.toISOString());
if (!confirm("Are you sure about this change?")) {
info.revert();
}
},
eventClick : function(info) {
//delete event from calender
info.event.remove();
}
});
calendar.render();
});
Full calendar version 4
How to remove event from calendar:
<div id="calendar"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new Calendar(calendarEl, {
events: [
{
id: '505',
title: 'My Event',
start: '2010-01-01',
url: 'http://google.com/'
}
// other events here
],
eventClick: function(info) {
info.jsEvent.preventDefault(); // don't let the browser navigate
if (info.event.id) {
var event = calendar.getEventById(info.event.id);
event.remove();
}
}
});
});
</script>
This worked for me. I hope, this will also help you. Thanks for asking this question.