'mustache.js date formatting
I have started using mustache.js and so far I am very impressed. Although two things puzzle me. The first leads on to the second so bear with me.
My JSON
{"goalsCollection": [
{
"Id": "d5dce10e-513c-449d-8e34-8fe771fa464a",
"Description": "Multum",
"TargetAmount": 2935.9,
"TargetDate": "/Date(1558998000000)/"
},
{
"Id": "eac65501-21f5-f831-fb07-dcfead50d1d9",
"Description": "quad nomen",
"TargetAmount": 6976.12,
"TargetDate": "/Date(1606953600000)/"
}
]};
My handling function
function renderInvestmentGoals(collection) {
var tpl = '{{#goalsCollection}}<tr><td>{{Description}}</td><td>{{TargetAmount}}</td><td>{{TargetDate}}</td></tr>{{/goalsCollection}}';
$('#tblGoals tbody').html('').html(Mustache.to_html(tpl, collection));
}
Q1 As you can see my 'TargetDate' needs parsing but I am unsure of how to do that within my current function.
Q2 Say I wanted to perform some function or formatting on one or more of my objects before rendering, what is the best way of doing it?
Solution 1:[1]
I've been using Mustache for my projects as well, due to its ability to be shared across client/server. What I ended up doing was formatting all values (dates, currency) to strings server-side, so I don't have to rely on helper Javascript functions. This may not work well for you though, if you're doing logic against these values client-side.
You might also want to look into using handlebars.js, which is essentially Mustache, but with extensions that may help with client-side formatting (and more). The loss here is that you will probably not be able to find a server-side implementation of handlebars, if that matters to you.
Solution 2:[2]
You can use a "lambda"
"TargetDate": "/Date(1606953600000)/",
"FormatDate": function() {
return function(rawDate) {
return rawDate.toString();
}
}, ...
Then in the markup:
<td>
{{#FormatDate}}
{{TargetDate}}
{{/FormatDate}}
</td>
From the link:
When the value is a callable object, such as a function or lambda, the object will be invoked and passed the block of text. The text passed is the literal block, unrendered.
Solution 3:[3]
I have created a small extension for Mustache.js which enables the use of formatters inside of expressions, like {{expression | formatter}}
You would anyway need to create a function that parses your date value like this:
Mustache.Formatters = {
date: function( str) {
var dt = new Date( parseInt( str.substr(6, str.length-8), 10));
return (dt.getDate() + "/" + (dt.getMonth() + 1) + "/" + dt.getFullYear());
}
};
And then just add the formatter to your expressions:
{{TargetDate | date}}
You can grab the code from here: http://jvitela.github.io/mustache-wax/
Solution 4:[4]
It's a long time ago but got on this looking for exactly the same. Mustachejs (now) allows you to call functions of the passed data and not only that; in the function the value of this
is whatever value is true in a section.
If my template is like this:
{{#names}}
<p>Name is:{{name}}</p>
<!-- Comment will be removed by compileTemplates.sh
#lastLogin is an if statement if lastLogin it'll do this
^lastLogin will execute if there is not lastLogin
-->
{{#lastLogin}}
<!--
formatLogin is a method to format last Login
the function has to be part of the data sent
to the template
-->
<p>Last Login:{{formatLogin}}</p>
{{/lastLogin}}
{{^lastLogin}}
not logged in yet
{{/lastLogin}}
{{#name}}
passing name to it now:{{formatLogin}}
{{/name}}
{{/names}}
And Data like this:
var data={
names:[
{name:"Willy",lastLogin:new Date()}
],
formatLogin:function(){
//this is the lastDate used or name based on the block
//{{#name}}{{formatLogin}}{{/name}}:this is name
//{{#lastLogin}}{{formatLogin}}{{/lastLogin}}:this is lastLogin
if(!/Date\]$/.test(Object.prototype.toString.call(this))){
return "Invalid Date:"+this;
}
return this.getFullYear()
+"-"+this.getMonth()+1
+"-"+this.getDate();
}
};
var output = Mustache.render(templates.test, data);
console.log(output);
Solution 5:[5]
You can get the timestamp using simple String methods:
goalsCollection.targetDate = goalsCollection.targetDate.substring(6,18);
Of course, this depends on your timestamp being the same length each time. Another option is:
goalsCollection.targetDate =
goalsCollection.targetDate.substring(6, goalsCollection.targetDate.length - 1);
These techniques aren't specific to Mustache and can be used to manipulate data for any library. See the Mozilla Developer Center Documentation on substring for more details.
Solution 6:[6]
To declare a function within a json you can always do this.
var json = '{"RESULTS": true, "count": 1, "targetdate" : "/Date(1606953600000)/"}'
var obj = JSON.parse(json);
obj.newFunc = function (x) {
return x;
}
//OUTPUT
alert(obj.newFunc(123));
Solution 7:[7]
Working example of a 'lambda' function for parsing an ISO-8601 date and formatting as UTC:
var data = [
{
"name": "Start",
"date": "2020-04-11T00:32:00.000-04:00"
},
{
"name": "End",
"date": "2022-04-11T00:32:00.000-04:00"
},
]
var template = `
{{#items}}
<h1>{{name}}</h1>
{{#dateFormat}}
{{date}}
{{/dateFormat}}
{{/items}}
`;
var html = Mustache.render(template, {
items: data,
dateFormat: function () {
return function (timestamp, render) {
return new Date(render(timestamp).trim()).toUTCString();
};
}
});
document.getElementById("main").innerHTML = html;
<script src="https://unpkg.com/[email protected]/mustache.min.js"></script>
<div id="main"></div>
If you want fancier date formatting you could use for example something like:
new Date().toLocaleDateString('en-GB', {
day : 'numeric',
month : 'short',
year : 'numeric', hour: 'numeric', minute: 'numeric'
})
// outputs '14 Apr 2022, 11:11'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | JVitela |
Solution 4 | HMR |
Solution 5 | jmort253 |
Solution 6 | jimmyo |
Solution 7 |