SharePoint list conditional formatting - US versus UK dates
-
20-12-2020 - |
Question
I've tried my best not to ask for help, but I'm stuck, even after I learned a bit of JS, MomentJS and Client Side Rendering on SP.
The code below returns undefined in date column. If you know why, please let me know.
// JavaScript Document
(function () {
var condFieldCtx = {};
// Define template variable
condFieldCtx.Templates = {};
// Define your required fields and functions to call in each case.
// In our case the field is Progress
// Override Function is PatientProgressViewTemplate
condFieldCtx.Templates.Fields = {
"Priority": {"View": PriorityFormat},
"PercentComplete": {"View": PercentCompleteFormat},
"b05o": {"View": CreateDateFormat}
};
//conditional formatting for a complete row comes here
condFieldCtx.OnPostRender = [HighlightRowOverride];
// Register the template override with SP2013
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(condFieldCtx);
})();
function CreateDateFormat(ctx)
{
var date = new Date();
var CreateDate = moment(ctx.CurrentItem.CreateDate).format('DD/MM/YYYY');
var now = moment().format('DD/MM/YYYY');
//Compare and react
if(now > CreateDate)
{
return "<span><font style='background-
color:red;display:block;'>"+ctx.CurrentItem.CreateDate+"</font>";
}
else if(now == CreateDate)
{
return "<span><font style='background-
color:yellow;display:block;'>"+ctx.CurrentItem.CreateDate+"</font></span>";
}
else
{
return ctx.CurrentItem.CreateDate;
}
}
Everything else works fine, as you can see below on the screenshot. It's just the dates I'm struggling with.
Please tell me what am I doing wrong.
Edit1:
OK, thanks to Danny, I finally got it sorted. I hope.
Below is the working code; ctx.CurrentItem.ColumnName reference had to be changed to the internal name b05o, some tweaking here and there..
function CreateDateFormat(ctx)
{
var CreateDate = moment(ctx.CurrentItem.b05o).format('DD/MM/YYYY');
var now = moment(date, "L", 'en-GB', true).format('DD/MM/YYYY');
//Compare and react
if(CreateDate == 'undefined' || !CreateDate)
{
return ctx.CurrentItem.b05o;
}
else if(now > CreateDate)
{
return "<span><font style='color:white;background-color:red;display:block;'>"+ctx.CurrentItem.b05o+"</font>";
}
else if(now == CreateDate)
{
return "<span><font style='background-color:yellow;display:block;'>"+ctx.CurrentItem.b05o+"</font></span>";
}
else if(now < CreateDate)
{
return "<span><font style='color:white;background-color:green;display:block;'>"+ctx.CurrentItem.b05o+"</font></span>";
}
else
{
return ctx.CurrentItem.b05o;
}
}
...and here's the result and working date formatting.
The only worry I have is the format of the date displayed in debugging:
The date entered in Item 6 is 31/12/2017 and as you can see it's formatted as green on the list, which is correct, but console.log shows it as 12/07/2019. Below, 05/06/2017 and 06/05/2017
console.log(now > CreateDate);
is displayed as true in debugger. Possibly not a big deal, but I'm worried that something is still nor right and it might cause issues in future.
Last problem I have is when I Stop editing the list I get the following error:
Not sure what to do with this :]
Edit2:
Danny showed me great and simple way for authoring the views live, but date 31/12/2017 still seems to be causing issues. It returns invalid date, probably because 12/31/2017 is invalid.
Edit3:
I had to fiddle with dates a bit to get it working, and here's what I did:
"b05o": {
View: function (ctx) {
var valueU = ctx.CurrentItem[this.Name].split("/");
var valueY = valueU[1] + "/" + valueU[0] + "/" +valueU[2];
var valueM = moment(valueY).format('DD/MM/YYYY');
var valueT = new Date(valueY);
var daysDiff = GetDaysAfterToday(valueT);
var color = '#ff6600'; // today dark orange
if (daysDiff > 0) color = 'green'; // future green
if (daysDiff < 0) color = 'red'; // past red
if (daysDiff > 0 && daysDiff < 30) color = '#ffad33'; //next 30 days turns orange
return String.format('<span style=background:{0};color:white>{1:d}</span>',color,ctx.CurrentItem[this.Name]);
}
And this is what I get:
Solution
Good, you found the issue with the internal name yourself, that is always the best way to make learning stick.
Some tips
avoid creating new List Fields with that "easy" SharePoint UI, that's how you get those stupid weird internal names.
Instead create new Fields in the List settings, where you specify the Internal name first (without spaces!), then rename the column to give its DisplayName (the first name will stick as Internal Name)Always use Chrome and the Cisar WYSIWYG CSR editor when editing CSR files
Don't hardcode fieldnames, the fieldname the function was called on is in the
this
JavaScript Scope asthis.Name
No need for the MomentJS library
If you only do simple date calculations, SharePoint provides aGetDaysAfterToday()
functionTry to write as less repeating code as possible, keeps your code readable and easy maintainable
The only string different in your long 3 SPAN lines is the colorSharePoints'
String.format()
method is very helpful to include parameters in Strings
And can format Dates to anything you want: Changing date format using javascriptThe <font> tag is no longer supported in HTML5, you set the style on the parent element
You code becomes something like:
"b05o": {
View: function (ctx) {
var value = new Date(ctx.CurrentItem[this.Name]);
var daysDiff = GetDaysAfterToday(value);
var color = 'yellow'; // today
if (daysDiff > 0) color = 'red'; // future
if (daysDiff < 0) color = 'green'; // past
return String.format('<span style=background:{0};color:white>{1:d}</span>',color,value);
}
notes
- style has no double-quotes
because DOM element attributes (without spaces) will be quoted (with ") by the browser
so you don't have to specify them in your code (unless they have spaces)