I have a kendo scheduler and I'm having a problem with move event. I can move only one event at a time and then I can't even grab any event afterwards. I think there's something wrong with the dates but I really can't figure out why. I tried dataSource with 2-3 events and it's working but when I put that exact same data in php and return it as json. It's not working.
Any help would be appreciated.
$("#scheduler").kendoScheduler({
date: new Date(),
startTime: new Date(today2()),
timezone: "Etc/UTC",
currentTimeMarker: false,
height: 800,
views:
[
"week",
{ type: "month", selected: true, eventHeight: 60}
],
dataSource:
{
transport:
{
read:
{
url: "tasks.php",
dataType: "json"
},
batch: true,
parameterMap: function (options, operation)
{
if (operation === "read") {
var scheduler = $("#scheduler").data("kendoScheduler");
var result =
{
start: scheduler.view().startDate(),
end: scheduler.view().endDate()
}
return kendo.stringify(result);
}
return kendo.stringify(options);
}
},
schema:
{
model:
{
id: "taskId",
fields:
{
taskId: { type: "number", from: "TT_CODE" },
start: { type: "date", from: "TT_START_DATETIME"},
end: { type: "date", from: "TT_END_DATETIME"},
title: { from: "TT_EDIT"}
}
}
}
}
});
php file with json data:
$json[0]['TT_CODE'] = 1;
$json[0]['TT_START_DATETIME'] = "2016-01-16 15:00:00";
$json[0]['TT_END_DATETIME']= "2016-01-16 16:00:00";
$json[0]['TT_EDIT'] = "Fast and furious 6";
echo json_encode($json);
Since you specified start and end as date in your model, the scheduler is expecting to received properly formatted date. While JSON passes date as string, javascript still expect the date string to be formatted.
In your case, it would be:
$json[0]['TT_CODE'] = 1;
$json[0]['TT_START_DATETIME'] = "2016-01-16T15:00:00.000Z";
$json[0]['TT_END_DATETIME']= "2016-01-16T16:00:00.000Z";
$json[0]['TT_EDIT'] = "Fast and furious 6";
You could also leave date as is and handle the string with a custom logic in the parameterMap function.
As a side note, if you have a doubt about the type formatting, go in the browser console and have a look at the network tab. You'll be able to compare the data sent by the working service to the data sent by PHP and see where is the difference.
Related
I am trying to convert the default date time format returned from a RepositoryRestResource in Spring Boot to a human readable format in jQuery Datatables. I found this Datatables plugin:
DataTables datetime plugin
I'm using it but getting "Invalid date"
I believe I need to specify the input date format to the plugin so moment.js can understand it to do the conversion but I'm not sure how to format the input format.
Here is my javascript DataTable script:
$('#invoices').DataTable({
"bFilter": true,
"autoWidth": true,
"processing": false,
"ajax": _link,
"sAjaxDataProp" : "_embedded.invoices",
"oLanguage": {
"sSearch": "<span>Filter:</span> _INPUT_" //search
},
columnDefs: [ {
targets: 0,
render: $.fn.dataTable.render.moment( 'YYYY-MM-DD' )
} ],
"columns": [
{ "data": "dropoff"},
{ "data": "ready" },
{ "data": "total_quantity" },
{ "data": "total_price" },
{ "data": "paid" }
]
});
Here's example of the service object data: _embedded.invoices
_embedded: {
invoices: [
{
dropoff: "2016-02-13T18:00:00.000+0000",
ready: "2016-02-15T14:00:00.000+0000",
note: "ZIPPER IS NIKEL",
paid: true,
total_price: 79.8,
total_quantity: 203,
_links: {
self: {
href: "http://localhost:8080/invoices/1"
},
invoice: {
href: "http://localhost:8080/invoices/1"
},
itemlines: {
href: "http://localhost:8080/invoices/1/itemlines"
},
customer: {
href: "http://localhost:8080/invoices/1/customer"
}
}
}
So you can see the date format above: "2016-02-15T14:00:00.000+0000"
It has the full date, time, and utc offset. I just want it to show date and time without seconds, something simple doesn't need to be fancy, just clean it up a little remove the T and UTC garbage at the end for the end users.
Appreciate the help!!!
For my HTML scripts I have them in this order, which doesn't seem to be causing a problem but here it is just in case:
<script src="/js/jQuery-2.2.3/jquery-2.2.3.js"></script>
<script src="/js/datatables.js"></script>
<script src="/js/datetime.js"></script>
<script src="/js/moment.js"></script>
I would suggest you define bean for Jackson configuration:
#Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
b.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
return b;
}
For more info check how to Customizing the Jackson ObjectMapper: With Spring Boot.
In an angular app I have a page that displays several Kendo-grids based on the data retrieved from an http request. The data comes back as json.
This is the function that executes on successful data retrieval. This is within a controller, and ctrl is the "this" object on the controller scope. Moment is a JavaScript library for managing dates. The only thing it's doing here is formatting as strings the date (MM/DD/YYYY) and the time (hh:mm A).
function (data) {
ctrl.dateGroups = {};
var currentDate = '';
data.Data.forEach(function (item) {
item.Date = item.StartDateTime ? moment(item.StartDateTime).format(HC_APP_CONFIG.dateFormat) : '';
item.ClockInTime = item.StartDateTime ? moment(item.StartDateTime).format(HC_APP_CONFIG.timeFormat) : '';
if ( angular.isEmpty(item.EndDateTime) ||
item.EndDateTime === '' ||
item.EndDateTime.format(HC_APP_CONFIG.dateFormat).match(HC_APP_CONFIG.badLocalDatePattern) !== null ){
item.ClockOutTime = '';
item.EndDateTime = '';
} else {
item.ClockOutTime = moment(item.EndDateTime).format(HC_APP_CONFIG.timeFormat);
}
var currentDate = 'd'+item.Date;
if (ctrl.dateGroups.hasOwnProperty(currentDate) &&
ctrl.dateGroups[currentDate].length > 0) {
ctrl.dateGroups[currentDate].push(item);
} else {
ctrl.dateGroups[currentDate] = [item];
}
});
}
The function (successfully) takes each returned item and puts it into an object as part of arrays named after the date, so that all items from Jan 14th, for example, end up in one array, and another for Jan 15th, etc.
This displays in the page with this loop:
<div class="col-sm-12" ng-repeat="(key,value) in punchList.dateGroups">
<h2 class="punch-heading">{{key.substring(1)}}</h2>
<div hc-grid id="grid-{{key}}"></div>
</div>
The result is a series of grids, each corresponding to a date and containing all the items for that date. This again, is successful.
The grid configuration:
gridConfig = {
uiOptions: {},
autoBind: false,
sortable: {
mode: 'single'
},
height: 'auto',
columnMenu: false,
filterable: false,
dataSource: {
type: 'json',
serverPaging: true,
serverFiltering: true,
serverSorting: true,
pageSize: HC_APP_CONFIG.defaultPageSize,
schema: {
data: 'Data',
total: 'TotalCount',
model: {
id: 'ShiftId',
fields: {
EmployeeName: {
type: 'string'
},
EmployeeCode: {
type: 'string'
},
JobName: {
type: 'string'
},
ClockIn: {
type: 'string'
},
ClockOut: {
type: 'string'
}
}
}
}
},
columns: [
{
field: 'EmployeeName',
title: 'Name',
sortable: false
},
{
field: 'EmployeeCode',
title: 'Employee Code',
sortable: false
},
{
field: 'JobName',
title: 'Job',
sortable: false
},
{
field: 'ClockInTime',
title: 'Clock In'
},
{
field: 'ClockOutTime',
title: 'Clock Out'
}
]
}
The problem is when I sort by the Clock In or Clock Out columns (the only sortable columns). At this point, the grid structure (pagination indicator, column heads, etc) remain in tact but the data disappears.
I'm using Kendo UI v2015.1.429
Kendo UI grids support direct server interaction via a built-in AJAX system for making API calls. It appears that setting serverSort:true may tell the Kendo UI grid to drop the current data model and query the server for newly sorted data (which it expects the server to provide). Since you are not using direct server interaction with the grid, it probably drops the model but then has no way to get a new one.
There is a sortable:true option that may be what you need for client side sorting of the existing data.
Link to Kendo UI grid server-side sorting article
I've implemented zabuto calendar in my project. Here is the screen shot:
.
I want the color of date cell to be changed when clicked. Here is a part of my code:
$(document).ready(function () {
$("#my-calendar").zabuto_calendar({
cell_border: true,
today: false,
show_days: true,
weekstartson: 0,
nav_icon: {
prev: '<i class="fa fa-chevron-circle-left"></i>',
next: '<i class="fa fa-chevron-circle-right"></i>'
}
});
});
Here is onClick code.
myDateFunction(this.id);
function myDateFunction(id) {
var date = $("#" + id).data("date");
document.getElementById("#" + id).style.color = "blue";
}
$("#my-calendar").zabuto_calendar({
action: function () {
return myDateFunction(this.id, false);
},
legend: [
{type: "text", label: "Special event", badge: "00"},
{type: "block", label: "Regular event"}
]
});
But this isn't working. How can I fix it?
Old post, but I've made a custom Zabuto calendar.
It's untested and lot's of features are missing but you should give it a peek:
$("#my-calendar").zabuto_calendar({
language: "fr",
year: 2015,
month: 1,
show_previous: 1,
show_next: 2,
// show_reminder: true,
// show_today: false,
// show_days: true,
// weekstartson: 0,
// nav_icon: {
// prev: '<i class="fa fa-chevron-circle-left"></i>',
// next: '<i class="fa fa-chevron-circle-right"></i>'
// },
callbacks: {
on_cell_double_clicked: function() {
return cellDoubleClicked(this);
},
on_cell_clicked: function() {
return cellClicked(this);
},
on_nav_clicked: function() {
return navClicked(this);
},
on_event_clicked: function() {
return eventClicked(this);
}
},
events: {
local: events_array,
ajax: {
url: "" // load ajax json events here...
}
},
legend: [
{label: "Rendez-vous", type: "appointment"},
{label: "Evenement A", type: "eventtype2"},
{label: "Evenement B", type: "eventtype3"},
{label: "<span class='fa fa-bell-o'></span> Rappel", type: "reminder"}
]
});
http://jsfiddle.net/n2gkm4d9/
(try double-click in day wrappers, simple-click on events)
Now with:
init calendar with local json + ajax data
call public methods (to add just one event at a time for example)
add event through a modal (not the modal included in zabuto calendar, I've removed it)
show a list of events of a day
...
It's only few hours of work, there's lot of features to add and things to do to make it stable but it's usable. ;-)
Look carefully to the code... there's much more than the fiddle show actually:
I think you should add a public method really easily to change the color of the cell.
Cheers
Fro
go through this http://zabuto.com/dev/calendar/examples/action.html. it contains your answer.
In the app I'm building, I have a data grid and some select boxes where the user can set filters and upon a selection it makes an AJAX call to get a new array of data from the server.
I have the grid initializing with default filters, but I can't figure out how to wipe the grid of all rows, and re-populate with a fresh array. I was trying dataView, but after reading some posts this seems to not be the answer. I find the official example-6 (ajax example) confusing.
I would like column sorting and column re-ordering to be retained when new data is loaded.
Here is the js I currently have which only initializes properly:
$(function(){
//update the grid when select values change
$('#qol_options :input').change(function(){
update_grid_data();
});
init_grid = function(){
// set grid options
var grid;
var columns = [
{id: "village", name: "Village", field: "village", sortable: true},
{id: "setting", name: "Setting", field: "setting", sortable: true},
{id: "hood", name: "N.hood", field: "hood", sortable: true},
{id: "timespan", name: "Time", field: "timespan", sortable: true},
{id: "count_0", name: "0", field: "count_0", sortable: true, width: 10},
{id: "count_1", name: "1", field: "count_1", sortable: true, width: 10},
{id: "count_2", name: "2", field: "count_2", sortable: true, width: 10},
{id: "count_3", name: "3", field: "count_3", sortable: true, width: 10},
{id: "count_4", name: "4", field: "count_4", sortable: true, width: 10},
{id: "count_6", name: "6", field: "count_6", sortable: true, width: 10},
{id: "count_7", name: "7", field: "count_7", sortable: true, width: 10},
{id: "count_8", name: "8", field: "count_8", sortable: true, width: 10},
{id: "count_total", name: "Total", field: "count_total", sortable: true},
{id: "pos_perc", name: "%", field: "pos_perc", sortable: true},
{id: "decile", name: "Decile", field: "decile", sortable: true},
];
var options = {
enableCellNavigation: true,
enableColumnReorder: true,
multiColumnSort: true
};
//get default grid data (all)
var grid_data = [{'village':0, 'setting':0, 'hood':0, 'timespan':0, 'count_0':0, 'count_1':0, 'count_2':0, 'count_3':0, 'count_4':0, 'count_6':0, 'count_7':0, 'count_8':0, 'count_total':0, 'pos_perc':0, 'decile':0}];
//create the grid instance
this_grid = new Slick.Grid("#data_table_container", grid_data, columns, options);
update_grid_data();
}
update_grid_data = function(){
var settingID = $('#settingID').val();
var villageID = $('#villageID').val();
var hoodID = $('#hoodID').val();
//init the grid
$.ajax({
type: "POST",
url: '<cfoutput>#APPLICATION.site_prefix#</cfoutput>/_global/ajax/ajax_handlers.cfm',
data: {'action': 'get_qol_report_data', 'villageID': villageID, 'settingID': settingID, 'hoodID': hoodID, 'itemID': 0, 'categoryID': 0},
dataType: 'json',
success: function(data) {
push_data_to_grid(data);
}
});
}
push_data_to_grid = function(data){
this_grid.setData(data);
this_grid.render();
}
//execute the grid init
init_grid();
});
I've faced the same problem. Please, try the below code.
function updateGridView(){
data_view.beginUpdate();
data_view.setItems(update_data);
data_view.endUpdate();
data_view.refresh();
grid.invalidate();
}
function grid_refresh(){
$.ajax("<cfoutput>#APPLICATION.site_prefix#</cfoutput>/_global/ajax/ajax_handlers.cfm",{
dataType : "json",
complete: function(xhr){
update_data = eval(xhr.responseText);
updateGridView();
}
})
}
Just call the grid_refresh() function.
I implemented something like this myself and here is how I have done it. I do use the dataview which will be wiped out every times and also the grid object which will be overwritten. I am not using your code, but instead I will show you the template which I use, I actually call the same function for loading & reloading but just make sure to empty() out the grid before you reload, see 1st line of code:
<div id="myGrid" style="width:100%;height:680px;"></div>
Then I made myself a button with an onclick event that looks something like this onclick=populateMyGrid() as a refresh button (it's actually a reload icon to make it nicer) and that event will call my function to reload the data through the $.getJSON() jQuery function, see the following code:
// Display some Market Indexes on a bar on top of the Grid
function populateMyGrid() {
// empty out the Grid before refreshing the data
$('#myGrid').empty();
// columns & options definition....
columns = [
{ id: "village", ............
];
options = {
enableCellNavigation: true,
editable: true,
............
};
ajaxURL = 'myPhpAjaxFileToPullData.php?action=getdata';
$.getJSON(ajaxURL, function (ServerResponse) {
dataView = new Slick.Data.DataView();
grid = new Slick.Grid('#myGrid', dataView, columns, options);
............
// initialize the model after all the events have been hooked up
dataView.beginUpdate();
dataView.setItems(ServerResponse.data);
dataView.endUpdate();
// Refresh the data render, if user only clicked on the refresh button instead of refreshing the whole page from browser
grid.updateRowCount();
grid.render();
}); // end of getJSON
} // end of populateMyGrid
From this code, the important part of it is to empty out the grid at first and then the last 2 rows of code for refreshing your grid with new data and make sure to re-render at last. That is the way I have it working, works like a charm...oh and I also display a text showing last refresh date+time, so it's more obvious to the user of how old the data is!
Even though it's not your code sample, you should get the idea...hope it helps :)
Also if you want to repopulate the grid with some kind of filtering you send the filtering via the ajaxURL of the $.getJSON or you could also replace it with a $.post and send it via the data property as your started, if you do it that way then move all your code into the success function (or a function call). Here is a possible solution for replacing the $.getJSON call... but please note that I did not try it but it should work:
//init the grid
$.ajax({
type: "POST",
url: '<cfoutput>#APPLICATION.site_prefix#</cfoutput>/_global/ajax/ajax_handlers.cfm',
data: {'action': 'get_qol_report_data', 'villageID': villageID, 'settingID': settingID, 'hoodID': hoodID, 'itemID': 0, 'categoryID': 0},
dataType: 'json',
success : getData
});
function getData() {
dataView = new Slick.Data.DataView();
grid = new Slick.Grid('#myGrid', dataView, columns, options);
............
// initialize the model after all the events have been hooked up
dataView.beginUpdate();
dataView.setItems(ServerResponse.data);
dataView.endUpdate();
// Refresh the data render, if user only clicked on the refresh button instead of refreshing the whole page from browser
grid.updateRowCount();
grid.render();
}
Handsontable makes it very easy to send table values from a server an array:
$('#dataTable').handsontable( data: serverdataarray )
So far, so good. However, I would like to format some of the columns in the array.
If I have a fixed number of columns I can easyly do this:
$('#dataTable').handsontable({
data: serverdataarray ,
columns: [
{ data: "Entity", type: 'text', renderer: orangeFF9900 },
{ data: "Geography", type: 'text', renderer: orangeFF9900 },
{ data: "Description", type: 'text', renderer: orangeFF9900 },
{ data: "cost_month1", type: 'numeric' },
{ data: "cost_month1", type: 'numeric' }
]
});
My problem is that the data sent from the server will have a varying number of columns depending on a number of factors. Thus, I would like to be able to generate the columns formating array dynamicaly on the server and send it as an array too. I.e.:
var cols = [
{ data: "Entity", type: 'text', renderer: orangeFF9900 },
{ data: "Geography", type: 'text', renderer: orangeFF9900 },
{ data: "Description", type: 'text', renderer: orangeFF9900 },
{ data: "cost_month1", type: 'numeric' },
{ data: "cost_month1", type: 'numeric' }
]; // Strictly speaking this would be a string sent form the server, but you catch my drift
$('#dataTable').handsontable({
data: serverdataarray ,
columns: cols
});
However, on doing so, I end up with the following error TypeError: method is not a function jquery.handsontable-0.9.9-full.js Line: 3028
The line in question (3028) is the return line of the following function:
Handsontable.TableView.prototype.applyCellTypeMethod = function (methodName, td, row, col) {
var prop = this.instance.colToProp(col)
, cellProperties = this.instance.getCellMeta(row, col)
, method = Handsontable.helper.getCellMethod(methodName, cellProperties[methodName]); //methodName is 'renderer' or 'editor'
return method(this.instance, td, row, col, prop, this.instance.getDataAtRowProp(row, prop), cellProperties);
};
Handsontable actualy manages to render correct number of columns on screen, although they are blank, unformatted and there is only one row so I'm gessing it is infering this much form the serverdataarray and not cols.
Any suggestions on how to achive what I am looking for?
I am open to changing the Handsontable sourcecode if need be.
Thanks
This answer is just intended as an expansion on #PostureOfLearning 's correct response:
It turns out the problem was caused by the following mistake and the fact that I simplified the code in the hope of making the post more readable:
var orangeFF9900= function (instance, td, row, col, prop, value, cellProperties) {
Handsontable.TextCell.renderer.apply(this, arguments);
$(td).css({
background: '#ff9900'
});
};
$.post('/AJAX/columns', function (data) {
var cellData = JSON.parse(data.Cells);
var colsData = JSON.parse(data.Cols);
$('#dataTable').handsontable({
data: cellData ,
columns: colsData
});
});
Now the colsData array looks like described above (or perhaps more precisely as):
[
{ "data": "Entity", "type": "text", "renderer": "orangeFF9900" },
{ "data": "Geography", "type": "text", "renderer": "orangeFF9900" },
{ "data": "Description", "type": "text", "renderer": "orangeFF9900" },
{ "data": "cost_month1", "type": "numeric" },
{ "data": "cost_month1", "type": "numeric" }
]
Now, because of the way text is transmitted in JSON via quote marks " ", orangeFF9900 is resolved as a string and not a function call.
Fortunately however, it appears we can teach HandOnTable to recognise a renderer function name passed as a string by using the following line:
Handsontable.cellLookup.renderer.orangeFF9900 = finction(…) {…};
Thus our final code can look like:
Handsontable.cellLookup.renderer.orangeFF9900 = function (instance, td, row, col, prop, value, cellProperties) {
Handsontable.TextCell.renderer.apply(this, arguments);
$(td).css({
background: '#ff9900'
});
};
$.post('/AJAX/columns', function (data) {
var cellData = JSON.parse(data.Cells);
var colsData = JSON.parse(data.Cols);
$('#dataTable').handsontable({
data: cellData ,
columns: colsData
});
});
Hope this helps someone in the future
Cheers
I don't see anything wrong with your approach.
In one of my projects, I'm successfully using:
var myCols = [...];
$('#dataTable').handsontable({
data: serverdataarray,
columns: myCols
});
In you sample code, the comment line "// Strictly speaking ...": At the beginning of the line you seem to have too many closing brackets. var cols = [...]}); should just be var cols = [...];
I'm assuming its a typo.
Except for that I suggest checking that the the columns data is set to exactly the same ID/name as the column has from the server and not i.e. what you want as a heading. Example:
var cols = [{ data: "RefNum" }, { data: "Qty"}];
Add headers using:
colHeaders: ["Reference", "Quantity"]
The last thing I can think of is that there is something wrong with the renderer. Try removing the renderer for each column and see if it works first. Its kind of hard to help without more code on this.