Show events in fullcalendar using ajax - javascript

I am writing application on asp.net core 2.0. and trying to show events stored in DB in calendar. I have added links to js and css files as it is shown in documentation. As event source I am using events as function as it is shown in official documentation Fullcalendar Doc but my calendar does not show events. It is empty!
GetEvents method in Schedules controller which gets data from DB
public ActionResult GetEvents()
{
return new JsonResult(Json(from events in _context.Schedules
select new { id = events.ID,
EventTitle = events.EmployeeID,
ShiftDate = events.ShiftDate.Date } ));
}
I also tried to modify ajax but it also does not work.
<div id="calendar"></div>
<script>
$(document).ready(function () {
$('#calendar').fullCalendar({
events: function (start, end, timezone, callback) {
$.ajax({
url: "/Schedules/GetEvents",
type: "POST",
dataType: "JSON",
success: function (result) {
var eventsList = [];
// alert(result); // --1--
// alert(JSON.stringify(result)); // --2--
$(result).each(function () {
var eventTitle = $(this).attr('EventTitle');
var eventStart = $(this).attr('ShiftDate');
var eventId = $(this).attr('id');
eventsList.push(
{
id: eventId,
title: eventTitle,
start: eventStart
});
});
if (callback)
callback(eventsList);
}
});
}
});
});
</script>
First alert shows message [Object object]..., Second alert shows all selected data in a "JSON string". But calendar does not show anything.
So, what am I doing wrong? Thank you!

Try this:
result.forEach(function (item) {
eventsList.push({
id: item.id, title: item.EventTitle, start: item.ShiftDate
})
})

Related

Full calendar resource extra params not added

I try to customize the params that send with the events and resources on the fullCalendar library.
I use full calendar version 3.
I can fetch these custom params from a form and assign them to events request.
But the issue is with resources that I use the same code for both but the requested URL for resource breaks and also lost the default start and end prams as well.
The code that I tried:
resources: {
// Resource route to load Instructors.
url: resourcesCallback,
method: 'GET',
data: function() {
var fields = jQuery('.calendar_filter_form').serializeArray();
var datas = {};
jQuery.each(fields, function(index, val) {
/* iterate through array or object */
datas[val.name] = val.value;
});
return datas;
},
failure: function() {
alert('There was an error while fetching instructors!');
},
},
and the event part:
events: {
// Resource route to load Instractors.
url: eventsCallback,
method: 'GET',
data: function() {
var fields = jQuery('.calendar_filter_form').serializeArray();
var data = {};
jQuery.each(fields, function(index, val) {
/* iterate through array or object */
data[val.name] = val.value;
});
return data;
},
failure: function() {
alert('there was an error while fetching events!');
},
}
The generated URL that I get are these:
For events:
Request URL: DOMAIN/load?instractor=&lessonType=&date=&start=2019-07-22T00%3A00%3A00&end=2019-07-23T00%3A00%3A00&_=156377682
For resources:
Request URL: DOMAIN/resources?_=1563776826863
I need to generate the second URL like the first, as you see the code is same but result is different, what is wrong?
The full code if needed:
$('#calendar').fullCalendar({
defaultView: 'agendaDay',
// Active the ajax reload the resources(instructors).
refetchResourcesOnNavigate: true,
// To make the time slot divided in 15mis.
slotDuration: "00:15:00",
displayEventTime : false,
// This define each time slot can get how many part
// of the rows, for example if we set it to "00:01:00"
// then it will divide each row by 15 mins but just show
// the one between one like: 00:15:00 , 00:45:00 , 01:15:00.
slotLabelInterval: "00:01:00",
slotLabelFormat: ['H:mm'],
groupByResource: true,
// To trun of the all day row at the top of calendar.
allDaySlot: false,
groupByDateAndResource: true,
// Settings for manage the calendar header options.
header: {
left: 'prev, today, next',
center: 'title',
right: null,
},
eventRender: function (event, $element) {
// Render the Main content of the events with more details
// and with html tags to be more user friendly.
$element.find('.fc-title').html('<p style="text-align:center">'
+ event.lessonType + ' ~ ' + event.student
+ '<br>' + event.description
+ '<br>' + event.lessonAvailable + '~' + event.nextEvent + '</p>'
);
},
// Define the Calendar column name.
// This part should be dynamic and will
// define by instructor names.
resources: {
// Resource route to load Instructors.
url: resourcesCallback,
method: 'GET',
data: function() {
var fields = jQuery('.calendar_filter_form').serializeArray();
var data = {};
jQuery.each(fields, function(index, val) {
/* iterate through array or object */
data[val.name] = val.value;
});
return data;
},
failure: function() {
alert('There was an error while fetching instructors!');
},
},
// The main part of getting data and manipulate them
// to show those in proper format in the calendar.
// To match with resources here the resourceId should match
// with the ids that provided in the resources.
// Also to get proper location according to time slot
// it need the correct start and end params that should
// be in correct date format like: 2019-07-18T19:30:00.
events: {
// Resource route to load instructors.
url: eventsCallback,
method: 'GET',
data: function() {
var fields = jQuery('.calendar_filter_form').serializeArray();
var datas = {};
jQuery.each(fields, function(index, val) {
/* iterate through array or object */
datas[val.name] = val.value;
});
return datas;
},
failure: function() {
alert('there was an error while fetching events!');
},
}
});
In the meantime, of course, the obvious workaround is to use the resources-as-function pattern instead, then you can construct the AJAX request exactly as you need it.
Thanks, #ADyson.
resources: function(callback){
jQuery('input[name="start"]').val(jQuery('#calendar').fullCalendar('getView').start.format());
jQuery('input[name="end"]').val(jQuery('#calendar').fullCalendar('getView').end.format());
jQuery.ajax({
url: resourcesCallback,
type: 'GET',
dataType: "json",
data: jQuery('.calendar_filter_form').serialize(),
error: function() {
// alert('Oops! Try again.');
},
success: function(response){
callback(response);
}
});
},

Unable to select the newly added selectize components post an ajax call

Unable to select the newly added selectize components post an ajax call
I have pre populated the options with the currently selected options, and trying to retrieve more option with an ajax call from the server.
My server returns data like this but I am not sure what to do with this data
[{"id":303,"name":"Short Sleeve Opening"}]
I've tried using the addOption and refreshOptions methods, but they doesn't seem to work.
Below is the piece of code which is invoking the selectize component.
$(function () {
$select_options = $('select').selectize({
plugins: ['restore_on_backspace', 'remove_button', 'drag_drop'],
delimiter: ',',
persist: false,
create: function (input) { // I am not sure if this is of any use, as I never found the control to enter in this part of code during debugging.
return {
value: input,
text: input
}
},
load: function (query, callback) {
if (!query.length) return callback();
$.ajax({
dataType: 'json',
url: '/measurement_tags/autocomplete_key?q=' + encodeURIComponent(query),
error: function () {
callback(); //Not sure what the callback should be, documenation is not self explanatory
},
success: function (res) {
//Added this callback to add the new options to the list, it is adding the new options to the list but I can't select them at all
//Moreover, second time I try to use autocomplete it doesn't work. The control doesn't reach the load method, and no error observed in console
for (index in res) {
$('.selectize-dropdown-content').append('<div class="option" data-selectable="" data-value="' + res[index].id + ' ">' + res[index].name + '</div>');
}
}
});
}
});
});
What is the exact way to add the new options to the list permanently?
Finally achieved this after wasting whole day:
$(function () {
$select_options = $('select').selectize({
plugins: ['restore_on_backspace', 'remove_button', 'drag_drop'],
delimiter: ',',
persist: false,
options: [],
load: function (query) {
$.ajax({
dataType: 'json',
url: '/measurement_tags/autocomplete_key?q=' + encodeURIComponent(query),
success: function (res) {
updateOptions(res);
}
});
}
});
var updateOptions = function (newOptions) {
var selectize = $select_options[0].selectize;
for (index in newOptions) {
selectize.addOption({
value: newOptions[index].id,
text: newOptions[index].name,
});
}
selectize.refreshOptions();
}
});

Correct way of redirecting view on AJAX 'success' in MVC app

Question background:
I've implemented a search feature in the header of my MVC site. Its features a input text-box with a 'Search' Button.
The Issue:
Currently I have implemented a AJAX function in the shared master layout.cshtml view that handles the click event of the search button, as shown:
$(document).ready(function () {
$(".searchBtn").click(function () {
var $searchTerm = $("#searchInput").val();
$.ajax({
url: '#Url.Action("ProductSearch", "Product")',
type: 'POST',
data: {
"searchTerm": $searchTerm,
"pageNumber": 0
},
success: function (result) {
window.location.href = result.url;
},
failure: function () {
alert('failed');
}
});
});
});
This is the ProductSearch method of the the Product Controller the AJAX call. The search term along with the page number is sent to the controller method:
public ActionResult ProductSearch(string searchTerm, int pageNumber)
{
if (searchId == 0)
{
searchId = 1;
}
var productDetailHandler = new ProductPageDBHandler(
new ProductDetailSqlServerHandler(new ProductDetailDataSetConvertor()));
var searchList = productDetailHandler.ProductSearch(searchTerm);
return View(searchList.ToPagedList(pageNumber, 3));
}
The problem is that this seems to not be returning the view I've associated with the ProductSearch method. How do I go about correctly redirecting to thw correct view once the user has submitted their search query?
Your ajax function is calling a method that returns a view. Change you success callback to
success: function (result) {
$('#someElement').html(result);
},
This will replace the contents of <div id="someElement"></div> with the returned view.

Kendo Grid C# - Select current page without refresh datasource again

i have been trying to fix this, what i want to do is:
I have a datasource who gets data from server, when i go to server, i get the list of items, then i have to search the item i have to select (This item could be in any page), after i have the item and the page where the item is located (assuming each page has 30 items), then i call LINQ expression to skip the required ammount of data and take 30. Finally i return this list to the client side.
When data arrives to client i need to "auto-select" the selected item and change the page to locate the user in the right page where the selected item is located. I have the new page, skip, selected value and everything in the client side again.
What do you suggest to me to change the page into the kendo grid datasource without call a new refresh and go to the server again?
This is how the datasource looks like:
return new kendo.data.DataSource({
serverPaging: true,
transport: {
read: {
url: URLController.Current().getURL('MyURL'),
contentType: 'application/json',
accepts: 'application/json',
type: 'POST'
},
parameterMap: function(data, type) {
if (data) {
return JSON.stringify(
{
data: jsonData,
pageSize: data.pageSize,
skip: data.skip,
take: data.take
});
}
}
},
schema: {
data: function (data) {
var dropDownData = JSON.parse(data);
gridElement.attr('data-model', JSON.stringify({ data: data }));
return dropDownData.Data;
},
total: function (data) {
var dropDownData = JSON.parse(data);
return dropDownData.total;
},
model: {
id: 'ID'
}
},
pageable: true,
pageSize: 30,
error: function(e) {
alert('Error ' + e);
}
});
When the grid data is bounded i have to change the page to current page number and then select the current item.
grid.one('dataBound', function (e) {
var currentGridElement = this.element;
var currentModel = currentGridElement.attr('data-model');
var currentJsonData = parseDropDownDataJSONString(currentModel).data;
var gridDataSource = this.dataSource;
var selection = gridDataSource.get(currentJsonData.selectedValue);
if (selection != undefined) {
var row = currentGridElement.find('tbody>tr[data-uid=' + selection.uid + ']');
if (row != undefined) {
currentGridElement.attr('data-closeByChange', false);
gridDataSource.page(currentJsonData.pageNumber);
this.select(row);
dexonDropDownGrid.combobox().text(selection.DISPLAY);
}
}
var aaaa = 0;
});
This is how my databound event listener looks like, when i try to set the page it calls again the server and i got more delay to load the right data.
Is there any way to solve this?
Thanks
Have the same problem.
There is how I fix that(not the best solution ever, but it works):
var forcedPageChange = false;
var cachedResult;
var dataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
if (forcedPageChange) { // prevent data request after manual page change
forcedPageChange = false;
options.success(cachedResult);
cachedResult = null;
return;
}
gridDataProvider.getData() // promise of data
.then(function (result) {
// check if current page number was changed
if ($scope.gridConfig.dataSource.page() !== result.pageNumber ||
$scope.gridConfig.dataSource.pageSize() !== result.rowsPerPage) {
cachedResult = _.clone(result);
forcedPageChange = true;
options.page = result.pageNumber;
options.pageSize = result.rowsPerPage;
$scope.gridConfig.dataSource.query(options);
}
options.success(result);
}, function () {
options.error();
});
}
},
schema: {
data: function (response) {
return response.items;
},
total: function (response) {
return response.totalCount;
}
},
//...
serverPaging: true,
serverSorting: true,
serverFiltering: true
});
I found that dataSource.page(newPageNumber) doesn't work in this situation. It just drop page number to 1.
This solution works, but I still have a bug with missing sorting icon after dataSource.query(options)...

Select2 - Ajax search - remember last results

I am using Select2 3.5.1. With this plugin I can successfully load remote data. However I am here today to ask a question to improve this search. Here is the step-by-step to understand what I would like to do:
Setup a Select2 with remote data loading (using ajax).
Click on the Select2 input and search for something.
The loading will appear and after some seconds you will see a list of results.
Click on one of the results listed - the box of results will then disappear.
If you click again on the search box, the list will be empty and you will need to type some new text again to have a list of results.
Is it possible that when we click again on the search box, that the list of results previously searched re-appear without any ajax call? Then if the user delete a character or change his search criteria it would then trigger the ajax search again.
If it is possible, how would we code that?
I hope my question is clear, please let me know if you have any questions. Thank you.
Here is a very simple code where we do a search that return a list of results. It doesn't really search, but it does return a list when you type something. I am not sure how to use the initSelection that is mentionned in one of the response.
<html>
<head>
<title>
Test page for ajax cache
</title>
<script type='text/javascript' src='../../resources/javascript/jquery/jquery-1.9.1.min.js'></script>
<link type='text/css' href='../../resources/javascript/select2/select2.css' rel='stylesheet' />
<script type='text/javascript' src='../../resources/javascript/select2/select2.js'></script>
<script>
$(document).ready(function(){
$('#select').select2({
ajax: {
type: 'POST',
url: 'ajax.php',
dataType: 'json',
data: function(term, page){
return {
autoc: 'country',
term: term
}
},
results: function(data, page){
console.log(data);
return( {results: data.results} );
}
},
placeholder: 'Search something',
minimumInputLength: 3,
width: '333'
});
});
</script>
</head>
<body>
<input type='text' name='inputdata' id='select' />
</body>
</html>
The very simple ajax.php called:
<?php
$results2['more'] = false;
$results2['results'][0] = array('id'=> "1", 'text'=> "California");
$results2['results'][1] = array('id'=> "2", 'text'=> "Canada");
$results2['results'][2] = array('id'=> "2", 'text'=> "Someword");
$results2['results'][3] = array('id'=> "2", 'text'=> "Alberta");
$results2['results'][4] = array('id'=> "2", 'text'=> "New York");
echo json_encode($results2);
I did read your post once again.
I misunderstood you last time.
The solution is here.
$(document).ready(function () {
$('#select').select2({
// this part is responsible for data caching
dataCache: [],
query: function (q) {
var obj = this,
key = q.term,
dataCache = obj.dataCache[key];
//checking is result in cache
if (dataCache) {
q.callback({results: dataCache.results});
} else {
$.ajax({
url: 'ajax.php',
data: {q: q.term},
dataType: 'json',
type: 'POST',
success: function (data) {
//copy data to 'cache'
obj.dataCache[key] = data;
q.callback({results: data.results});
}
})
}
},
placeholder: 'Search something',
width: '333',
minimumInputLength: 3,
});
// this part is responsible for setting last search when select2 is opening
var last_search = '';
$('#select').on('select2-open', function () {
if (last_search) {
$('.select2-search').find('input').val(last_search).trigger('paste');
}
});
$('#select').on('select2-loaded', function () {
last_search = $('.select2-search').find('input').val();
});
});
This will make another ajax call but with the same query string as before. Uses event select2:closing to save last query string and select2:open to insert the string into the search input and trigger input event.
var lastQueryString = '';
jQuery(".my-select2").select2({
minimumInputLength: 2,
placeholder: "Select an option",
ajax: {
url: "/example",
data: function (params) {
var query = {
search: params.term
}
return query;
},
processResults: function (data) {
return {
results: JSON.parse(data)
};
}
}
});
jQuery('.my-select2').on('select2:open', function () {
if (lastQueryString) {
jQuery('.select2-search').find('input').focus().val(lastQueryString).trigger('input');
}
});
jQuery('.my-select2').on('select2:closing', function () {
lastQueryString = jQuery('.select2-search').find('input').val();
});

Categories

Resources