Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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/

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

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.

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));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top