Date format in SlickGrid - slickgrid

SlickGrid launches the calendar using a default US date format of mm/dd/yyyy. I store dates in my database in Australian format dd/mm/yyyy. how can I change the format of the calendar to take dd/mm/yyyy?

You can use the DatePicker of your choice by writing a new custom editor. The default date editor uses jQueryUI DatePicker.
Personally (I'm in Australia too), I use the default with the following settings:
function DateFormatter(rowIndex, cell, value, columnDef, grid, dataProvider) {
if (value == null || value === "") { return "-"; }
return moment.utc(value).format('ddd, D MMM YYYY');
}
... using moment.js to format the date, and in the DateEditor ...
$input.datepicker({
showOn: "button",
changeMonth: true,
changeYear: true,
dateFormat: 'd/m/yy',
buttonImageOnly: true,
buttonImage: "../images/calendar.gif"
});
Also you could just localise

You can write formatter for row (i use moment.js too):
function dateTimeFormatter (row, cell, value, columnDef, dataContext) {
var dateTime = Date.parse(value);
var result = moment(dateTime);
return result.format('DD.MM.YYYY hh:mm:ss');
}

First, add code to the slick.formatters.js file in your local library:
Add the custom date formatter in two spots:
$.extend(true, window, {
"Slick": {
"Formatters": {
"PercentComplete": PercentCompleteFormatter,
"PercentCompleteBar": PercentCompleteBarFormatter,
"YesNo": YesNoFormatter,
"Checkmark": CheckmarkFormatter,
"Checkbox": CheckboxFormatter,
"Date": Dateformatter //<< this one
}
}
});
and on the end of the file:
function Dateformatter(row, cell, value, columndef, datacontext) {
if (value === null) {
return "";
} else {
var d = new Date(value);
var m = d.getMonth() + 1;
return (d.getDate() + "/" + m + "/" + d.getFullYear());
}
}
})(jQuery); //<< this line is already present
Now you can add the date formatter in your column definitions:
{
id: "lastLoginDate", name: "LastLoginDate", field: "lastLoginDate", formatter: Slick.Formatters.Date
},

Related

jqGrid Unformatter for predefined formatter

I have a jqGrid where the formatter function for the colModel must be defined as a string
{name:'FileSize', index:'FileSize', width:90, editable: true,
formatter: 'fileSizeFormatter'}
I can't use the following where the formatter function is not a string because I build the colmodels on the server side in C#. If I could use the non string formatter Defining unformatter would be a solution as shown in
Here
{name:'FileSize', index:'FileSize', width:90, editable: true,
formatter: fileSizeFormatter}
And here is the fileSizeFormatter I needed to use fn.fmatter because my formatter is passed as a string and the code assumes it is one of the predefined one's lile "select", "currency"...etc
$.fn.fmatter.fileSizeFormatter = function (cellval, options) {
var fileUnit = "B";
if (cellval) {
var fileUnit;
var iKBFileSize;
if (cellval < 1024) {
iKBFileSize = cellval;
} else {
iKBFileSize = cellval / 1024;
fileUnit = "KB";
}
var result = iKBFileSize.toFixed(1) + fileUnit;
return result;
}
return cellval + fileUnit;
};
Sample
So the question is how can I define unformatter for a formatter which is passed as a string. When I do grid.getrowdata or edit the cell my unformatter is not being used. It is getting me the data with the file unit.
$.unformat.fileSizeFormatter = function (cellvalue, options, cell) {
return $('input', cellval).is(":checked") ? true : false;
};
You should define unformatter in a little another way:
$.fn.fmatter.fileSizeFormatter.unformat = function (cellValue, options, elem) {
return $(elem).find('input').is(":checked") ? true : false;
}
You should define unformatter of cause after defining the formatter ($.fn.fmatter.fileSizeFormatter).

Kendo treelist - trying to set a column template

I'm working with a Kendo treelist widget, and disappointed to see there's no rowTemplate option as there is on the Kendo grid.
I see a columnTemplate option (i.e. http://docs.telerik.com/kendo-ui/api/javascript/ui/treelist#configuration-columns.template ), but this will affect the entire column.
However, I need to drill into each cell value and set a css color property based on a ratio ( i.e. If value/benchmark < .2, assign <span style='color:red;'> , but my color value is dynamic.
There's a dataBound: and dataBinding: event on the treelist, but I'm still trying to figure out how to intercept each cell value and set the color once I've done my calculation.
var treeOptions = {
dataSource: ds,
columns: colDefs,
selectable: true,
scrollable: true,
resizable: true,
reorderable: true,
height: 320,
change: function (e) {
// push selected dataItem
var selectedRow = this.select();
var row = this.dataItem(selectedRow);
},
dataBound: function (e) {
console.log("dataBinding");
var ds = e.sender.dataSource.data();
var rows = e.sender.table.find("tr");
}
};
and this is where I'm building out the `colDefs' object (column definitions):
function parseHeatMapColumns(data, dimId) {
// Creates the Column Headers of the heatmap treelist.
// typeId=0 is 1st Dimension; typeId=1 is 2nd Dimension
var column = [];
column.push({
"field": "field0",
"title": "Dimension",
headerAttributes: { style: "font-weight:" + 'bold' + ";" },
attributes : { style: "font-weight: bold;" }
});
var colIdx = 1; // start at column 1 to build col headers for the 2nd dimension grouping
_.each(data, function (item) {
if (item.typeId == dimId) {
// Dimension values are duplicated, so push unique values (i.e. trade types may have dupes, whereas a BkgLocation may not).
var found = _.find(column, { field0: item.field0 });
if (found == undefined) {
column.push({
field: "field2",
title: item.field0,
headerAttributes: {
style: "font-weight:" + 'bold'
}
,template: "<span style='color:red;'>#: field2 #</span>"
});
colIdx++;
}
}
});
return column;
}
**** UPDATE ****
In order to embed some logic within the template :
function configureHeatMapColumnDefs(jsonData, cols, model) {
var colDef = '';
var dimId = 0;
var colorProp;
var columns = kendoGridService.parseHeatMapColumns(jsonData, dimId);
// iterate columns and set color property; NB: columns[0] is the left-most "Dimension" column, so we start from i=1.
for (var i = 1; i <= columns.length-1; i++) {
columns[i]['template'] = function (data) {
var color = 'black';
if (data.field2 < 1000) {
color = 'red';
}
else if (data.field2 < 5000) {
color = 'green';
}
return "<span style='color:" + color + ";'>" + data.field2 + "</span>";
};
}
return columns;
}
Advice is appreciated.
Thanks,
Bob
In the databound event you can iterate through the rows. For each row you can get the dataItem associated with it using the dataitem() method (http://docs.telerik.com/kendo-ui/api/javascript/ui/treelist#methods-dataItem)
Once you have the dataitem, calculate your ration and if the row meets the criteria for color, change the cell DOM element:
dataBound: function (e) {
var that = e.sender;
var rows = e.sender.table.find("tr");
rows.each(function(idx, row){
var dataItem = that.dataItem(row);
var ageCell = $(row).find("td").eq(2);
if (dataItem.Age > 30) {
//mark in red
var ageText = ageCell.text();
ageCell.html('<span style="color:red;">' + ageText + '</span>');
}
}
DEMO
UPDATE: you can also do this with a template:
$("#treelist").kendoTreeList({
dataSource: dataSource,
height: 540,
selectable: true,
columns: [
{ field: "Position"},
{ field: "Name" },
{ field: "Age",
template: "# if ( data.Age > 30 ) { #<span style='color:red;'> #= data.Age # </span> #}else{# #= data.Age # #}#"
}
],
});
DEMO

How to modifly kendoDatasource filter in requestStart

I have the following requestStart in my kendoDatasource:
requestStart: function (e) {
var oldFilters = e.sender._filter ? e.sender._filter.filters : [],
endDateTime;
$.each(oldFilters, function (index, currFilter) {
if (currFilter.field === 'StatusChangeDate' && currFilter.operator == 'eq') {
endDateTime = new Date(currFilter.value.getYear(), currFilter.value.getMonth(), currFilter.value.getDay(), 23, 59, 59);
oldFilters.push({ field: currFilter.field, operator: 'gt', value: currFilter.value });
oldFilters.push({ field: currFilter.field, operator: 'lt', value: endDateTime });
oldFilters.splice(index, 1);
}
});
if (e.sender._filter) {
e.sender._filter.filters = oldFilters;
}
},
I want to change DateTime filter when it's operator is 'eq', in order to disable filter precision.
But when I modify filter in requestStart like in the code above, it doesn't work. The request sends with old filter.
I don't know what I'm doing wrong. Is there another way to achieve behavior like this?
By the time requestStart is called, the query is already committed to being sent as is. The event is just letting you know but doesn't give you the opportunity to change anything.
Rather than try to sneak in the back way, just call the dataSource's filter() method to filter any way you want. DataSource will filter the data either locally or make a request to the server depending on the value of the serverFiltering option.
var filters = myDataSource.filter() || [],
endDateTime;
$.each(filters, function (index, currFilter) {
if (currFilter.field === 'StatusChangeDate' && currFilter.operator == 'eq') {
endDateTime = new Date(currFilter.value.getYear(), currFilter.value.getMonth(), currFilter.value.getDay(), 23, 59, 59);
filters.push({ field: currFilter.field, operator: 'gt', value: currFilter.value });
filters.push({ field: currFilter.field, operator: 'lt', value: endDateTime });
filters.splice(index, 1);
}
});
// Now apply the new filter to the dataSource.
// This will generate a request if serverFiltering == true.
myDataSource.filter(filters);
One other note, you should try to avoid accessing any property that starts with "_" as in "e.sender._filter". This is generally considered to be a "private" property which could change with the next version. You can get the current filter by calling filter() with no arguments as in the code above. This is another general rule in Kendo, no args mean get a value, args mean set a value.
EDIT
You can also hijack the CRUD requests to modify and/or add parameters using the dataSource's transport.parameterMap property. Note that this method will not modify the dataSource's filter properties. It only changes the request parameters going to the server.
$("#myGrid").kendoGrid({
// Column definitions, etc...
dataSource = new kendo.data.DataSource({
transport: {
// create, read, update, destroy definitions...
parameterMap: function(data, type) {
if ((type === "read") && data.filter && data.filter.filters) {
var filters = data.filter.filters;
for (var index = 0; index < filters.length, index++) {
var currFilter = filters[index];
if (currFilter.field === 'StatusChangeDate' && currFilter.operator == 'eq') {
endDateTime = new Date(currFilter.value.getYear(), currFilter.value.getMonth(), currFilter.value.getDay(), 23, 59, 59);
filters.push({ field: currFilter.field, operator: 'gt', value: currFilter.value });
filters.push({ field: currFilter.field, operator: 'lt', value: endDateTime });
filters.splice(index, 1);
break;
}
});
}
return data;
}
}
}),
});

How do you make a kendo datepicker do date validation for a minimum date?

I have the following control:
#(Html.Kendo().DatePickerFor(model => model.Attributes.DueDate)
.HtmlAttributes(new {
ID = "idSurvey_DueDate",
#data_bind = "value: DueDate",
#Class = "report-label datepicker surveyAttributesData",
TabIndex = 3 })
.Min(DateTime.Now)
)
And the following jquery:
$("#idSurvey_DueDate").kendoValidator({
rules: {
dateValidation: function (e) {
var currentDate = kendo.parseDate($(e).val());
// Check if date parse was successful
if (!currentDate) {
return false;
}
return true;
}
},
messages: {
dateValidation: "Invalid Date!",
min: "Date must not be in the past!"
}
});
When I test this out and enter in an invalid date the message I get isn't what I expect. Instead it is "The field DueDate must be a date." Where is this mystery message coming from and why isn't it using the messages property I put in the validator? All I want is for non-valid date formats to not be allowed and for the date to not be in the past. So a minimum must be enforced.
This code seems to work fine:
$("form").kendoValidator({
rules: {
dateValidation: function(element) {
var value = $(element).val();
var date = kendo.parseDate(value);
if (!date) {
return false;
}
return true;
},
minDate: function(element) {
var value = $(element).val();
var date = kendo.parseDate(value);
var result = date >= new Date();
return result;
}
},
messages: {
dateValidation: "You must enter a date",
minDate: "The date must not be in the past"
}
});
Here is a live demo: http://jsbin.com/EvoroRe/1/edit
I suggest to add the mvcdate rule:
rules: {
mvcdate: function (input) {
var datarole = $(input).data('role');
if (datarole === 'datepicker') {
var value = $(input).val();
if (value) {
var date = kendo.parseDate(value, 'ddd, MMM d');
if (!date) {
return false;
}
}
}
return true;
}
},
messages: {
mvcdate: function (intput) {
return intput.attr('data-val-date');
}
}
Unfortunatelly dateValidation rule has a lower priority that date and mvcdate just because they are default and nor custom one. As I have understood the mvcdate rule has the highest priority because:
dateValidation rule has been skipped for the certain control and I got the 'must be a date' error
date rule has been passed with the TRUE result but I still got the 'must be a date' error
mvcdate rule has helped me alone.
You always can look to the kendoValidator in the console:
I'm not sure if the kendo validator changed since the accepted answer, but you'll want to filter out and only apply date validation to datepicker inputs. Otherwise a textbox or other input will generate an error message about an invalid date. The rules should look like
$("#modForm").kendoValidator({
rules: {
dateValidation: function (input) {
if (input.is('[data-role="datepicker"]')) {
var value = $(input).val();
var date = kendo.parseDate(value);
if (!date) {
return false;
}
}
return true;
}
},
messages: {
dateValidation: "You must enter a date",
}
});

how to use monthNames in jqgrid when validating date?

In my jqgrid when i am clicking on add new record i have date field prepopulated with current date. Format of the date is yyyy-MMM-d (e.g. 2010-Jan-23).
Date is required field and when i click submit button it fails validation and displays error that this date is invalid, and it wants Y-m-d format.
How can i check my value with jqgrid? In other words how to make jqgrid accept the following date format when validating 2010-Jan-23?
Thanks.
Here is my JSON data:
{"rows":[
{"id":1,"cell":["2010-Mar-3","Pepto","2","False","not active"]},
{"id":2,"cell":["2009-May-6","Tylenol","5","False","not active"]},
{"id":3,"cell":["2008-May-6","Aspirin","9","True","active"]}
]}},
Here is my date column definition:
{ name: 'Date',
index: 'date',
width: '80px',
align: 'center',
sortable: false,
editable: true,
datefmt: 'Y-M-d',
editoptions: { dataInit: function(elem) { $(elem).datepicker({ dateFormat: 'yy-M-d' });},value: getDate } ,
editrules: { required: true, date:true} },
The getdate function inserts current date into field. here is the function:
function getDate(){
var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var now = new Date();
return now.getFullYear() + "-" + monthNames[now.getMonth()] + "-" + now.getDate();
}
Maybe this is because of this function? Can i insert current date from datepicker?
Amount of data sent from the server is not too big (about 10-30 rows) and this application will be used by maximum of 50 people, so there is no concerns regarding amounts of data.
Anytime when i have value as 2010-Jun-23 in the field, i get error message:Enter valid date value - Y-M-d
Verify that you defined datefmt: 'Y-M-d' in the column definition of colModel. In the list of editrules options (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:common_rules#editrules) is defined that if you use date: true as a editrules option, the validation will be done corresponds with the datefmt option.
Some more recommendations if you use date in jqGrid:
If you not yet use, think about of the usage of jQuery.datepicker (see http://jqueryui.com/demos/datepicker/#date-formats) inside of dataInit function of editoptions (like
editoptions: {
dataInit : function (elem) {
$(elem).datepicker();
}
// ...
}
in the simplest case). If you use searching for date fields, you can use dataInit with jQuery.datepicker also in searchoptions in the same way (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:singe_searching#colmodel_options). The usage of jQuery.datepicker in jqGrid is very easy, but it makes your program more comfortable.
Usage of standard date formatter (formatter: 'date') can be useful to convert source data format send to jqGrid to the new format which will be displayed. For example,
formatter: 'date', formatoptions: {srcformat:'y-m-d', newformat: 'Y-M-d' }
It is less interesting, but it can reduce a little the size of data send from server to client.
UPDATED: I must admit, I don't tested my suggestion with exactly your data format. Just now I tested all one more time and then read carefully jqGrid documentation about datefmt (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options). For datefmt are only numerical format for months is supported! So the value at the time of date verification must be in a numerical format. What can we do? For example following
we define as parameters of navGrid function "add" parameters (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:navigator parameter prmAdd) like following:
{ beforeCheckValues: function(posdata, formid, mode) {
var data = posdata.Date;
var dateParts = data.split("-");
var mounth = dateParts[1];
var mounths = $.jgrid.formatter.date.monthNames;
var iMounth = -1;
for (var i=0; i<12; i++) {
if (mounth === mounths[i]) {
iMounth = i;
break;
}
}
if (iMounth !== -1) {
posdata.Date = dateParts[0]+'-'+(iMounth+1)+'-'+dateParts[2];
}
},
beforeSubmit: function(postdata, formid) {
var data = postdata.Date;
var dateParts = data.split("-");
var mounths = $.jgrid.formatter.date.monthNames;
postdata.Date = dateParts[0]+'-'+
$.jgrid.formatter.date.monthNames[dateParts[1]-1]+
'-'+dateParts[2];
return [true,""];
}
}
So we convert the Date field to the numerical format inside of beforeCheckValues function and then convert all back to the original format (like 2010-Jan-23) after usage of checkDate. It will work.
The main question is now: have we some advantage from such kind of the date checking? We can just don't use editrules: { date:true } and implement our own date checking inside of beforeSubmit function. If we find out the wrong date we should return [false,"My error message"] and our custom error message "My error message" will be displayed by jqGrid.
So the easiest solution of your problem we receive if we could change the date format to any numerical form (Y-mm-d, mm/d/Y or another one). Usage of datepicker will makes for users the format problem not very important. Think about this and choose the way which your prefer.
I was facing similar issue. I have resolved it using custom function for validation. I am suing date format as '23-Jan-05'. You may modify it to suit your required date format.
function datecheck(value, colname) {
var dateParts = value.split("-");
var datePart = dateParts[0];
var mounth = dateParts[1];
var yearPart = dateParts[2];
var mounths = $.jgrid.formatter.date.monthNames;
var monthPart = -1;
for (var i = 0; i < 12; i++) {
if (mounth === mounths[i]) {
monthPart = i + 1;
break;
}
}
var dateText = monthPart + '-' + datePart + '-' + yearPart;
var date = Date.parse(dateText);
if (isNaN(date))
return [false,"Invalid date. Format expected: dd-mmm-yy. (23-Jul-05)"];
else
return [true,""];
}
JQGrid column details:
colModel: [name: 'JoiningDate', align: "center", editable: true,
editrules: { custom: true, custom_func: datecheck },
formatter: 'date', formatoptions: { srcformat: 'y-m-d', newformat: 'd-M-y' }, edittype: 'text', editable: true,
editoptions: { dataInit: function (el) { setTimeout(function () { $(el).datepicker({ dateFormat: 'd-M-y' }); }, 200); } }
},
Hope this helps.
Regards,
Abhilash

Resources