How to refresh fullcalendar using native javascript - javascript

I'm using fullcalendar library.
I'm not using query with this library but native javascript. I'm able to create and delete events. But when I do I have to refresh to get it to show. I would like for the calendar to automatically refresh after an event is created or deleted.
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
let model = document.getElementById('my-modal');
var calendar = new FullCalendar.Calendar(calendarEl, {
timeZone: 'UTC',
initialView: 'timeGridWeek',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
editable: true,
selectable: true,
events: {!! $data !!},
select: function(event) {
let _token = "{{ csrf_token() }}";
let data = {
'title': 'Event 1',
'start': event.startStr,
'end': event.endStr,
};
fetch("{{ route('booking.calendar.create') }}", {
method: 'post',
data: data,
headers: {
'X-CSRF-TOKEN': _token,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => console.log(data));
},
eventChange: function(e) {
let _token = "{{ csrf_token() }}";
let data = {
'title': 'Event 1',
'start':e.event.start,
'end': e.event.end,
};
fetch("http://hair_booking.test/booking/update/" + e.event.id, {
method: 'post',
headers: {
'X-CSRF-TOKEN': _token,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
})
.catch(function (error){
console.log(error);
})
},
eventClick: function(e) {
e.preventDefault;
var event = confirm('Do you want to delete this event');
if(event) {
let _token = "{{ csrf_token() }}";
let data = {
'title': 'Event 1',
'start':e.event.start,
'end': e.event.end,
};
fetch('http://hair_booking.test/booking/delete/' + e.event.id, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': _token,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => {
response.json()
})
.then(data => data)
.catch(error => {
console.error(error);
});
}
}
});
calendar.render();
});
Here's my laravel route file
Route::middleware(['auth'])->group(function() {
Route::get('/booking', [HairBooking::class, 'render'])->name('booking.calendar');
Route::post('/booking/create', [HairBooking::class, 'create'])->name('booking.calendar.create');
Route::post('/booking/update/{id}', [HairBooking::class, 'updateEvent'])->name('booking.calendar.update');
Route::delete('/booking/delete/{id}', [HairBooking::class, 'deleteEvent'])->name('booking.calendar.delete');
});
Here's my Component blade file to populate the events.
<?php
namespace App\Http\Livewire;
use App\Models\Booking;
use Carbon\CarbonImmutable;
use Livewire\Component;
use Illuminate\Http\Request;
class HairBooking extends Component
{
public function create(Request $request) {
$booking = new Booking();
$booking->title= 'Event 1';
$booking->user_id = auth()->user()->id;
$booking->start = $request->input('start');
$booking->end = $request->input('end');
$booking->save();
return $booking;
}
public function updateEvent(Request $request, $id) {
$event = Booking::find($id);
$event->start = $request->input('start');
$event->end = $request->input('end');
$event->save();
return $event;
}
public function deleteEvent(Request $request, $id) {
$event = Booking::find($id);
$event->delete();
return response()->json(null, 204);
}
public function render()
{
$data = Booking::all()->toJson();
return view('livewire.hair-booking', [
'data' => $data
]);
}
}
And here's my model really bare model.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Booking extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'title',
'start',
'end',
'allDay'
];
protected $guarded = [];
protected $casts = [
'start' => 'datetime',
'end' => 'datetime'
];
public function user() {
return $this->belongsTo(User::class);
}
}
Any help would be appreciated.

Related

How to delete an event from fullcalendar on button click?

I'm in the middle of developing a drag and drop event fullcalendar with a resource column. I'm able to drag and drop events on the calendar and save it to the database. For the resource column, I have an add room button that allows users to add the room which also gets saved in the database. The resources and events are successfully being fetched and displayed on the calendar.
Now, I'm working on developing the delete functionality for the same. For now, I'm stuck at deleting the events using a double click.
Here's the code:
main.js
document.addEventListener("DOMContentLoaded", function() {
var containerEl = document.getElementById("external-events");
var checkbox = document.getElementById("drop-remove");
new FullCalendarInteraction.Draggable(containerEl, {
itemSelector: ".fc-event",
eventData: function(eventEl) {
return {
title: eventEl.innerText
};
}
});
var calendarEl = document.getElementById("calendar");
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: "GPL-My-Project-Is-Open-Source",
plugins: ["interaction", "resourceTimeline", 'dayGrid', 'timeGrid' ],
header: {
left: "promptResource today prev,next",
center: "title",
right: 'dayGridMonth,resourceTimelineDay,resourceTimelineWeek'
},
customButtons: {
promptResource: {
text: "+ room",
click: function() {
var title = prompt("Room name");
console.log(title);
if (title) {
fetch("add_resources.php", {
method: "POST",
headers: {
'Accept': 'text/html'
},
body: encodeFormData({"title": title}),
})
.then(response => response.text())
.then(response => {
calendar.addResource({
id: response,
title: title
});
})
.catch(error => console.log(error));
}
}
}
},
editable: true,
aspectRatio: 1.5,
defaultView: "resourceTimelineDay",
resourceLabelText: "Rooms",
resources: "all_resources.php",
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,
eventClick: function (info) {
var confimit = confirm("Do you really want to delete?");
if (confimit) {
$.ajax({
type: "POST",
url: "delete_event.php",
data: "&id=" + info.event.id,
success: function (response) {
if(parseInt(response) > 0) {
$('#calendar').fullCalendar('removeEvents', info.event.id);
displayMessage("Deleted Successfully");
}
}
});
}
},
eventReceive: function(info) {
console.log(calendar.getResources());
console.log(info.event);
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"),
resourceid: info.event._def.resourceIds[0]
};
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;
};
delete_event.php
<?php
require "connection.php";
$id = $_POST['id'];
$conn = DB::databaseConnection();
$sql = "DELETE FROM Events WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $id);
if ($stmt->execute()) {
return $stmt->fetch(PDO::FETCH_ASSOC);
} else {
return null;
}
?>
When I'm trying to delete an event using the above code, I double click on the event, I see the message asking if I really want to delete the event, but it doesn't really get deleted. I don't see the delete_event.php being called in the network panel. The console has the error "ReferenceError: $ is not defined". I'm not sure what is wrong in the code above.
You need to make a few modifications to your code.
1) use fetch() instead of $.ajax, then you won't get any error messages about jQuery being missing. Ensure you put the event ID into the body of the request.
2) use the fullCalendar v4 syntax for eventClick, instead of v3 - see https://fullcalendar.io/docs/eventClick.
3) Remove the $stmt->fetch command from your PHP - a SQL DELETE operation doesn't return any results, so there is nothing to fetch. I also removed the meaningless return statements, because you're not inside a function, and your script doesn't have any further code which needs to be prevented from executing.
eventClick:
eventClick: function (info) {
var confimit = confirm("Do you really want to delete?");
if (confimit) {
fetch("delete_event.php", {
method: "POST",
body: encodeFormData({"id": info.event.id}) });
}
}
}
delete_event.php:
<?php
require "connection.php";
$id = $_POST['id'];
$conn = DB::databaseConnection();
$sql = "DELETE FROM Events WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $id);
if ($stmt->execute()) {
echo true;
} else {
echo false;
}
?>

How to update image with AJAX in Laravel

I'm having problems updating a record with an image. I don't what I need to do. My image is stored in a public folder called 'img/products'
ProductController.php
This is my controller. It works well without modifying the image.
public function update(Request $request, $id)
{
$validator = Validator::make($request->input(), array(
'name' => 'required',
'category_id' => 'required',
'description' => 'required',
'price_neto' => 'required',
'iva' => 'required',
'price_total' => 'required',
'image' => '',
));
if ($validator->fails()) {
return response()->json([
'error' => true,
'messages' => $validator->errors(),
], 422);
}
$products = Product::find($id);
$products->name = $request->input('name');
$products->category_id = $request->input('category_id');
$products->description = $request->input('description');
$products->price_neto = $request->input('price_neto');
$products->iva = $request->input('iva');
$products->price_total = $request->input('price_total');
$products->image = $request->input('image');
$products->save();
return response()->json([
'error' => false,
'products' => $products,
], 200);
}
Product.js
All I know is that I have to use var formData = new FormData ($ ("# frmAddProduct") [0]); as in the store function. I can enter records with images but not edit them. My image is stored in a public folder called 'img/products'
$(document).ready(function() {
$("#btn-edit").click(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: 'PUT',
url: '/product/' + $("#frmEditProduct input[name=product_id]").val(),
data: {
name: $("#frmEditProduct input[name=name]").val(),
category_id: $("#frmEditProduct select[name=category_id]").val(),
description: $("#frmEditProduct input[name=description]").val(),
price_neto: $("#frmEditProduct input[name=price_neto2]").val(),
iva: $("#frmEditProduct input[name=iva2]").val(),
price_total: $("#frmEditProduct input[name=price_total2]").val(),
image: $("#frmEditProduct input[name=image]").val(),
},
dataType: 'json',
success: function(data) {
$('#frmEditProduct').trigger("reset");
$("#frmEditProduct .close").click();
window.location.reload();
},
error: function(data) {
var errors = $.parseJSON(data.responseText);
$('#edit-product-errors').html('');
$.each(errors.messages, function(key, value) {
$('#edit-product-errors').append('<li>' + value + '</li>');
});
$("#edit-error-bag").show();
}
});
});
});
function editProductForm(product_id) {
$.ajax({
type: 'GET',
url: '/product/' + product_id,
success: function(data) {
$("#edit-error-bag").hide();
$("#frmEditProduct input[name=name]").val(data.products.name);
$("#frmEditProduct select[name=category_id]").val(data.products.category_id);
$("#frmEditProduct input[name=description]").val(data.products.description);
$("#frmEditProduct input[name=price_neto2]").val(data.products.price_neto);
$("#frmEditProduct input[name=iva2]").val(data.products.iva);
$("#frmEditProduct input[name=price_total2]").val(data.products.price_total);
$("#frmEditProduct file[name=image]").val(data.products.image);
$("#frmEditProduct input[name=product_id]").val(data.products.id);
$('#editProductModal').modal('show');
},
error: function(data) {
console.log(data);
}
});
}
You should check if the file exists before trying to delete, for example:
$product = Product::find($id);
if(!$product)
{
return response()->json(['error' => 'Product not found'], 404);
}
if (Storage::disk('local')->exists('img/products/'.$product->image)) {
Storage::disk('local')->delete('img/products/'.$product->image);
}
Take a look one example only:
public function update(UpdateProductFormRequest $request, $id)
{
$product = Product::find($id);
$data = $request->only('name','category_id','description',
'price_neto','iva','price_total');
if(!$product)
{
return response()->json(['error' => 'Product not found'], 404);
}
// when saving the file, delete the old file first
if ($request->hasFile('image')) {
$file = $request->file('image');
$original_filename = $file->getClientOriginalName();
// $mime = $file->getMimeType(); // Suggestion
$extention = $file->getExtension();
// $size = $file->getClientSize(); // Suggestion
$stored_filename = $original_filename; // md5($original_filename); // Suggestion
$file_path = storage_path('public/img/products/');
if (Storage::disk('local')
->exists("public/img/products/{$stored_filename}.{$extention}"))
{
Storage::disk('local')
->delete("public/img/products/{$recordSet->stored_filename}.{$extention}");
}
$file_moved = $file->move($file_path, "{$stored_filename}.{$extention}");
$data->image = "{$stored_filename}.{$extention}";
}
// Updating data
$result = $product->update($data);
if ($result) {
/* return redirect()
->route('products.index')
->withSuccess('Product was successfully updated'); */
return response()->json([
'message' => 'Product was successfully updated'
'product' => $product
]); // You don't have to put 200 because it's the default
}
/* return back()
->withErrors(['Unable to update the product'])
->withInput($request->input()); */
return response()->json(['error' => 'Unable to update the product'], 400);
}
It would be better if you create a form request to do your validations.
Don't forget to create links to the storage path:
php artisan storage:link
I think it would be helpful:
$("#btn-edit").click(function() {
var formData = new FormData($("#frmAddProduct")[0]);
formData.append('_method', 'put');
formData.append('_token', "{{ csrf_token() }}"); // if you are using Blade
var route= "{{ route('products.update', ['id' => ':id']) }}"; // if you are using Blade
route= route.replace(':id', $("#frmEditProduct input[name=product_id]").val())
$.ajax({
method: 'post',
url: route,
data: formData,
dataType: 'json',
success: function(data) {
$('#frmEditProduct').trigger("reset");
$("#frmEditProduct .close").click();
window.location.reload();
},
error: function(data) {
var errors = $.parseJSON(data.responseText);
$('#edit-product-errors').html('');
$.each(errors.messages, function(key, value) {
$('#edit-product-errors').append('<li>' + value + '</li>');
});
$("#edit-error-bag").show();
}
});
});
Is your js script in "Blade" ? If so, try it this way:
var image = '{{ asset("/img/products/_image_file") }}'
image.replace('_image_file', data.products.image)
$("#frmEditProduct file[name=image]").val(image)
Note that we can first use the "asset ()" helper to create the full path to use to find the image, but with a "_image_file" placeholder
After that, we use the replace () function to change the "_image_file" placeholder with the actual image file brought from the ajax response.
Something like this?
ProductController.php
public function update(Request $request, $id)
{
$validator = Validator::make($request->input(), array(
'name' => 'required',
'category_id' => 'required',
'description' => 'required',
'price_neto' => 'required',
'iva' => 'required',
'price_total' => 'required',
'image' => '',
));
if ($validator->fails()) {
return response()->json([
'error' => true,
'messages' => $validator->errors(),
], 422);
}
$products = Product::find($id);
if ($request->hasFile('image')) {
$productImage = $request->file('image');
$productImageName = rand() . '.' . $productImage->getClientOriginalExtension();
if (Storage::disk('local')->exists("img/products/{$productImageName}")) {
Storage::disk('local')->delete("img/products/{$recordSet->$productImageName}");
}
$file_moved = $productImage->move(public_path('img/products'), $productImageName);
$data->image = "{$productImageName}";
}
$products->save([
'name' => $request->name,
'category_id' => $request->category_id,
'description' => $request->description,
'price_neto' => $request->price_neto,
'iva' => $request->iva,
'price_total' => $request->price_total,
'image' => $productImageName,
]);
return response()->json([
'error' => false,
'products' => $products,
]);
}
Product.js
$("#btn-edit").click(function() {
var formData = new FormData($("#frmEditProduct")[0]);
formData.append('_method', 'put');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: 'POST',
url: '/product/' + $("#frmEditProduct input[name=product_id]").val(),
data: formData,
dataType: 'json',
success: function(data) {
$('#frmEditProduct').trigger("reset");
$("#frmEditProduct .close").click();
window.location.reload();
},
error: function(data) {
var errors = $.parseJSON(data.responseText);
$('#edit-product-errors').html('');
$.each(errors.messages, function(key, value) {
$('#edit-product-errors').append('<li>' + value + '</li>');
});
$("#edit-error-bag").show();
}
});
});

How to return javascript success data to jQuery property [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
The below function is working fine and I am getting response from ajax get function, the data is comming in 'res.data.value' in JSON format, Now i want to pass this data to events property of full calender in array format. If i am passing static values to events property it is working fine. Please help me as I am unable to pass 'res.data.value' value dynamically.
<script>
$(document).ready(function() {
var completedInterviews = function() {
var requestParams = [];
requestParams = {
"url": dashboardServiceUrl + '/dashboard/widget/completedinterview',
"requestType": "GET",
"headers": {
"Accept": "application/json"
}
}
var res = makeRequest(requestParams);
res
.done(function(res) {
return [res.data.value];
})
.fail(function(err) {
console.log(err);
});
};
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listWeek'
},
defaultDate: '2018-03-12',
editable: true,
navLinks: true,
eventLimit: true,
events: completedInterviews(), // I want [res.data.value] value here.
loading: function(bool) {
$('#loading').toggle(bool);
}
});
});
</script>
/*
* function to make API call using AJAX, Deffered and Promise
*/
function makeRequest(requestParams) {
var headers = {
'Authorization': 'Bearer ' + authToken
};
// concating extra headers
headers = jsonConcat(headers, requestParams.headers);
// checking return content type
var dataType = "json";
if(headers.Accept == "application/xml") {
dataType = "xml";
}
var deferred = $.Deferred();
var response = $.ajax({
url: requestParams.url,
type: requestParams.requestType,
dataType: dataType,
data: JSON.stringify(requestParams.params),
headers: headers,
success: function(res) {
if(res.error != null) {
deferred.reject(res.error);
if(res.error=="Invalid Token") {
//window.location.href = "";
}
} else {
deferred.resolve(res);
}
},
error: function(err) {
deferred.reject(err);
}
});
return deferred.promise();
}
Use calendar in then statement.
<script>
$(document).ready(function() {
var completedInterviews = function() {
var requestParams = [];
requestParams = {
"url": dashboardServiceUrl + '/dashboard/widget/completedinterview',
"requestType": "GET",
"headers": {
"Accept": "application/json"
}
}
res = makeRequest(requestParams);
//RETURN RES
return res;
};
//WRAP CALENDAR WITH THEN
completedInterviews().then(function(data){
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listWeek'
},
defaultDate: '2018-03-12',
editable: true,
navLinks: true,
eventLimit: true,
events: data, // ADD DATA.
loading: function(bool) {
$('#loading').toggle(bool);
}
});
});
});
</script>

Laravel 5.4 Ajax save

Hi I am trying to make an save / create an item using ajax.
I am not that familiar with ajax and wanted to ask which steps I have to do next to make the save / create function make work.
How do I get the data and save it in my database.
So far my ajax code looks like this:
$(document).ready(function() {
$("#save-item").click(function(e) {
e.preventDefault();
var id = $('#item-id').data('item-id');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
}
});
$.ajax({
url: 'joke/create',
type: 'post',
data: {
id: id,
content: $('#item').val()
},
success: function(data) {
console.log("Success with data " + data);
},
error: function(data) {
console.log("Error with data " + data);
}
});
});
});
And my Controller looks like this:
public function create(Request $request)
{
$item = new Item;
if($data->save())
{
return response()->json(["response" => 200, "joke" => $item]);
}
else
{
return response()->json(["response" => 400, "joke" => $item]);
}
}
try this inside your controller:
$item = new Item;
$data = $request->all();
$item->create($data);
$item = new Item;
$data = $request->all();
if($item->create($data))
{
return response()->json(["response" => 200, "joke" => $item]);
}
else
{
return response()->json(["response" => 400, "joke" => $item]);
}

Showing events for multiple eventSources depend on checkboxes' choice in Fullcalendar

I'm adding the feature like in Solgema Fullcalendar - http://plone.org/products/solgema.fullcalendar/releases/2.1.2
(selecting and showing events with checkboxes selection)
My eventSourses look like:
eventSources: [
...
{
url: '/admin_schedule/get_schedule_db_recurring_events_on_daysweek/',//"<?echo $data_path?>",
type: 'GET',
data: {sch_teacher_id: sch_teacher_id},
backgroundColor: 'red',
}
],
And I want implement checkboxes for "filtering" events by teachers, checked in checkboxes. For beginning make just one checkbox (later make foreach cover)
<div class="box">
<?php
$js = 'onClick="rerender_schedule()"';
echo form_checkbox('teacher', 'vika', FALSE, $js)." Vika";
?>
</div>
By this code as I think, fullcalendar must call rerender_schedule() function which filters data from eventSource with vika's sch_teacher_id
If somebody could help with rerender_schedule() function, I will be thankful, because not good in ajax.
EDIT: (thanks to tocallaghan!). It's just a beginning right now.
My 3 checkboxes:
$data = array(
'name' => 'teacher',
'class' => 'teacher',
'id' => 'teacher',
'value' => '128',
'checked' => FALSE,
'style' => 'margin:10px',
);
echo form_checkbox($data); echo "Вика";
$data = array(
'name' => 'teacher',
'class' => 'teacher',
'id' => 'teacher2',
'value' => '111',
'checked' => FALSE,
'style' => 'margin:10px',
);
echo form_checkbox($data); echo "Вася";
$data = array(
'name' => 'teacher',
'class' => 'teacher',
'id' => 'teacher3',
'value' => '1',
'checked' => FALSE,
'style' => 'margin:10px',
);
echo form_checkbox($data); echo "Саша";
ajax on change them:
$('.teacher').change(function (event) {
events1.data.sch_teacher_id = $(this).val();
events2.data.sch_teacher_id = $(this).val();
events3.data.sch_teacher_id = $(this).val();
$calendar.fullCalendar('refetchEvents');
});
vars for eventSourses:
var events1 = {
url: 'url1',
type: 'GET',
data: {sch_teacher_id: $('#teacher').val() },
success: function (response) {
return response;
}
};
var events2 = {
url: 'url2',
type: 'GET',
data: {sch_teacher_id: $('#teacher').val() },
backgroundColor: 'green',
success: function (response) {
return response;
}
};
var events3 = {
url: 'url3',
type: 'GET',
data: { sch_teacher_id: $('#teacher').val() },
backgroundColor: 'red',
success: function (response) {
return response;
}
};
my eventSources call
eventSources: [
events1,
events2,
events3
],
You need refetchEvents , but be careful to update you data parameter before calling (otherwise it will remain the initially set value)
$('.CheckBoxClass').change(function () {
events.data.sch_teacher_id = $(this).val();
$('#calendar').fullCalendar('refetchEvents');
});
Edit: code to declare events object:
var events = {
url: 'url',
type: 'GET',
data: { Id: $('#divId').val() },
success: function (response) {
return response;
}
};
$('#calendar').fullCalendar({
events: events
});

Categories

Resources