Full calendar resource extra params not added - javascript

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);
}
});
},

Related

Fullcalendar 4: update info event from modal Bootstrap

I'm trying to update info date event from modal Bootstrap in Fullcalendar version 4.
My test:
Read event json
Click on event calendar, open modal, show info event and set value of a field with information to update
When I click on green button "Salva" (Save), doSubmitEdit function is called. It should:
close modal;
receive text field edited;
update via ajax my db;
update calendar event if necessary
But when then button is clicked I have this error:
q
TypeError: calendar.fullCalendar is not a function
on this line:
var event_obj_arr = calendar.fullCalendar('clientEvents', calendario_id);
(function ($) {
'use strict';
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
locale: 'it',
plugins: ['dayGrid', 'timeGrid', 'list', 'interaction', 'bootstrap'],
themeSystem: 'bootstrap',
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
navLinks: true, // can click day/week names to navigate views
selectable: true,
selectMirror: true,
editable: true,
eventLimit: true, // allow "more" link when too many events
events: {
url: '/_admin/vendor/fullcalendar/php/get-events.php',
failure: function () {
document.getElementById('script-warning').style.display = 'block';
}
},
eventClick: function (info) {
$('.card-body h4').html(info.event.start.toDateString());
$('.card-body p').html(info.event.title + '<br>' + info.event.extendedProps.autista + ' / Info: ' + info.event.extendedProps.autista_description);
$('#calendario_id').val(info.event.id);
$('#btnModal').trigger('click');
},
loading: function (bool) {
document.getElementById('loading').style.display =
bool ? 'block' : 'none';
}//,
});
calendar.render();
$('#submitButtonEdit').on('click', function (e) {
// We don't want this to act as a link so cancel the link action
e.preventDefault();
doSubmitEdit();
});
function doSubmitEdit() {
// get event object
var event_obj_arr = calendar.fullCalendar('clientEvents', calendario_id);
var event_obj = event_obj_arr[0];
// edit
$("#createEventModalEdit").modal('hide');
console.log($('#autista_description').val());
console.log($('#calendario_id').val());
// update event object properties
event_obj.extendedProps.autista_description = $('#autista_description').val();
// post to server
$.ajax({
url: '/_admin/vendor/fullcalendar/php/planning-aggiorna.asp',
data: 'type=changetitle&title=' + title + '&calendario_id=' + calendario_id,
type: 'POST',
dataType: 'json',
success: function (response) {
if (response.status == 'success') {
// nothing to do here
// update calendar, you may put this line into success method
calendar.fullCalendar('updateEvent', event_obj);
}
},
error: function (e) {
alert('Error processing your request: ' + e.responseText);
}
});
}
}).apply(this, [jQuery]);
Is it possibile to access fullcalendar class outside of it?
Thank you.
Here's the solution, thank to #Adison.
We have elements retrieved from modal form, update of live calendar (where I appended "changed" text to event's title) and update of db.
function doSubmitEdit() {
// get values from modal form
var calendario_id = $('#calendario_id').val();
var calendario_descrizione = $('#calendario_descrizione').val();
// get event object by id
var event = calendar.getEventById(calendario_id);
var title = event.title;
// post to server and update db
$.ajax({
url: '/_admin/planning-aggiorna.asp',
data: 'calendario_descrizione=' + encodeURIComponent(calendario_descrizione) + '&calendario_id=' + calendario_id,
type: 'POST',
dataType: 'text',
success: function (response) {
if (response == 'success') {
// update calendar
event.setProp('title', title + ' changed');
event.setExtendedProp('autista_description', calendario_descrizione);
}
},
error: function (e) {
alert('Error processing your request: ' + e.responseText);
}
});
}

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();
}
});

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)...

Cannot refresh TreeStore in EXTjs

I'm trying to create a web-page in EXTJs that has two major components:
A Form (Ext.form.Panel)
A Panel (Ext.tree.Panel)
The form is supposed to get some values, which should populate tree in second panel. In the button handler of the first panel I have access to the updated JSON object, but I cannot figure out a way to refresh the TreeStore that will update the display in tree.Panel.
This is what I have so far :
Ext.define('TreeServiceData',{
config:{
data : ''
},print : function() {
console.log("Printing data: ")
console.log(this.data.children[0])
}
});
var dataObject = Ext.create('TreeServiceData');
dataObject.setData({'expanded':false,'children':[{'text':'Master','expanded':true,'leaf':false,'children':[{'text':'Child 1','expanded':true,'leaf':false,'children':[{'text':'Child 2','expanded':true,'leaf':false,'children':[{'text':'Child 3','expanded':false,'leaf':false}]}]}]}]})
Ext.define('TreeStoreData',{
extend: 'Ext.data.TreeStore',
model: 'TaskModel',
autoLoad: true,
autoSync: true,
proxy: {
type:'memory',
reader: {
type:'json'
}
},
root:dataObject.getData()
});
var treeStore = Ext.create('TreeStoreData');
Now I'm trying to update and display the value of this treestore on a button call which looks like this :
buttons:[
{
text:'Get CCP/Product',
handler:function (btn, evt) {
dataObject.print();
treeStore.removeAll();
dataObject.setData({'expanded':false,'children':[{'text':'Master11','expanded':true,'leaf':false,'children':[{'text':'Child 12','expanded':true,'leaf':false,'children':[{'text':'Child 23','expanded':true,'leaf':false,'children':[{'text':'Child 34','expanded':false,'leaf':false}]}]}]}]})
dataObject.print();
}
}
]
But on this button handler I'm always getting a "Uncaught TypeError: Cannot call method 'indexOf' of undefined " on treeStore.removeAll() method, where treestore is clearly defined in this context.
Question 1) What is the correct way to refresh a TreeStore ?
Answer 1)
Instead of:
treeStore.removeAll();
dataObject.setData( ... );
You should do:
dataObject.setData( ... ); // This won't affect the store
treeStore.setRootNode(dataObject.getData()); // Actually update the store
Note that changing dataObject's data won't affect the store automatically like you seem to think...
this code works for me (ExtJS 4.2.1)
Total tree panel nodes refresh example:
var responseDictObjects = $.ajax({
data: { Id: this.idDictionary },
dataType: "json",
type: "POST",
cache: false,
url: 'http://' + config.domain + '/' + 'api/Dictionaries/GetDictTreeData',
async: false
}).responseText;
responseDictObjects = jQuery.parseJSON(responseDictObjects);
while (this.storeDict.getRootNode().firstChild) {
this.storeDict.getRootNode().removeChild(this.storeDict.getRootNode().firstChild);
}
this.storeDict.getRootNode().appendChild(responseDictObjects.Data);
Replace this.storeDict with your store reference.
In my case:
JSON.stringify(responseDictObjects.Data)
returns
"[{"id":8,"text":"kkk","leaf":false,"expanded":true,"children":null},{"id":17,"text":"ttttt","leaf":false,"expanded":true,"children":null},{"id":22,"text":"gggg","leaf":false,"expanded":true,"children":null},{"id":23,"text":"qqq","leaf":false,"expanded":true,"children":null},{"id":24,"text":"fff","leaf":false,"expanded":true,"children":null},{"id":27,"text":"fff","leaf":false,"expanded":true,"children":null},{"id":28,"text":"ggggggggggggggggggg","leaf":false,"expanded":true,"children":null},{"id":31,"text":"ttttttttttt666666666","leaf":false,"expanded":true,"children":null},{"id":32,"text":"ffffffffffffffffffff","leaf":false,"expanded":true,"children":null},{"id":33,"text":"kkkkkkkkkkkkk","leaf":false,"expanded":true,"children":null},{"id":35,"text":"7777777777","leaf":false,"expanded":true,"children":null},{"id":36,"text":"999999999999","leaf":false,"expanded":true,"children":null},{"id":37,"text":"iii","leaf":false,"expanded":true,"children":null}]"
I found another bug with TreePanel, previosly removed nodes appears after executing appendChild. So i started to use jquery tree plugin (dynatree). All you need is to create empty panel. And after render a panel, embed tree, in my case:
Create empty panel:
that.treePanel = Ext.create('Ext.panel.Panel', {
title: 'Records',
width: 350,
height: 400
});
After rendering panel you can refresh nodes whenever you want:
var that = this;
var responseDictObjects = $.ajax({
data: { Id: this.idDictionary },
dataType: "json",
type: "POST",
cache: false,
url: 'http://' + config.domain + '/' + 'api/Dictionaries/GetDictTreeData',
async: false
}).responseText;
responseDictObjects = jQuery.parseJSON(responseDictObjects);
var el = this.treePanel.getId();
if (this.treeDict == null) {
this.treeDict = $('#' + el).dynatree({
onActivate: function (node) {
that.treeDict.lastSelectedId = node.data.index;
},
children: []
});
}
this.treeDict.dynatree("getRoot").removeChildren(true);
this.treeDict.dynatree("getRoot").addChild(responseDictObjects.Data);

add custom params to fullcalendar request

I'm want to add a parameter named foo to the request that fullcalendar submits when retrieving event data. According to the docs this can be achieved using:
var getFoo() = function() {
// implementation omitted
};
$('#calendar').fullCalendar({
loading: function(isLoading) {
// CAN I SOMEHOW UPDATE foo FROM HERE?
},
events: {
url: '/myfeed.php',
type: 'POST',
data: {
foo: getFoo()
}
}
});
I want the value of the foo parameter to be calculated each time the calendar event data is requested, but it seems that fullcalendar only calls getFoo() the first time it loads, then re-uses that value for each subsequent request.
I've tried using this the loading event that is triggered immediately before the data is loaded, but I can't figure out how to update the foo paramter from within this function.
Update
I followed the advice below and got it working with this:
$('#calendar').fullCalendar({
events: function(start, end, callback) {
$.ajax({
url: 'getCalendarEvents',
dataType: 'json',
data: {
start: Math.round(start.getTime() / 1000),
end: Math.round(end.getTime() / 1000),
foo: getFoo()
},
success: function(doc) {
var events = eval(doc);
callback(events);
}
});
},
});
Maybe you could use the events as function to create your own ajax request.
var getFoo() = function() {
// implementation omitted
};
$('#calendar').fullCalendar({
events: function(start, end, callback) {
var myFoo = getFoo();
$.ajax({
url: 'myxmlfeed.php',
dataType: 'xml',
data: {
// our hypothetical feed requires UNIX timestamps
start: Math.round(start.getTime() / 1000),
end: Math.round(end.getTime() / 1000),
foo: myFoo
},
success: function(doc) {
var events = [];
$(doc).find('event').each(function() {
events.push({
title: $(this).attr('title'),
start: $(this).attr('start') // will be parsed
});
});
callback(events);
}
});
}
});
Try setting lazyFetching to false. I'm guessing you're having this problem because fullCalendar tries to save you from unnecessary ajax requests.
Fullcalendar doc on lazyFetching

Categories

Resources