Search code examples
javascriptjsondust.js

How to display JSON values dynamically using DustJS


var data = {
  response: [
    { name: "Moe", age:  37,salary: 10000 },
    { name: "James", age:  31, salary: 12000 },
    { name: "Jan", age:  28, salary: 9000 },
    { name: "David", age:  29, salary:8500 }
  ]
};

var gridDef = {
  "data":data,
  "columnDef":[
    { "field":"name", "columnName":"Name" },
    { "field":"Age", "columnName":"Age" },
    { "field":"Salary", "columnName":"salary" }
  ]
}

var source = '<table id="dustGoals"> ' +
    '<thead> <tr> ' +
    '{#columnDef}' +
    '<th style="border:1px;background-color: cyan">{columnName}</th> ' +
    '{/columnDef} ' +
    '</tr> </thead> ' +
    '<tbody> {#data.response}' +
    '<tr>' +
      '{#columnDef}' +
        '<td>{eval(response[field])}</td>' + //field is "name","Age","salary" key and want to display values of response JSON array above.
      '{/columnDef}' +
    ' </tr> '+
    '</tbody>{/data.response}'+
    '</table>';

var compiled = dust.compile(source,"goalTemplate");
dust.loadSource(compiled);
dust.render("goalTemplate", gridDef,
function(err, out) {
  document.getElementById('dustPlaceholder').innerHTML = out;
});

I need to display data.response values dynamically. How can I use the field property of each object in columnDef to display the associated value in the response?

In this example columnDef will loop three times with the field values name, age, and salary.


Solution

  • The format of this data is not ideal for Dust. Because Dust does not recursively render a template, you'll have to do more iterations than you otherwise would need. The ideal answer would be to reformat the data that your server sends so that all relevant fields are part of the same object.

    For example, because of your requirement to display fields dynamically, the server data should really look more like:

    [
      [ "Moe", 37, 10000 ],
      [ "James", 31, 12000 ],
      ...
    ]
    

    You would then be able to just iterate over arrays.

    If you can't change the server's data format, you need to write a context helper to extend Dust. Here's one possible solution, but you could write this in many ways.

    {
      fieldsFromColumnDef: function(chunk, context, bodies, params) {
        // Grab the fields we want to display
        var fields = context.resolve(params.columnDef).map(function(field) {
          return field.field;
        });
    
        // The current context will be a single item from results
        var row = context.current();
    
        // For each field name, render the body of the helper once with
        // the correct data
        fields.forEach(function(field) {
          chunk = chunk.render(bodies.block, context.push(row[field]));
        });
    
        return chunk;
      }
    }
    

    Your template would look like this:

    {#data.response}
      <tr>
        {#fieldsFromColumnDef columnDef=columnDef}
          <td>{.}</td> <!-- the dot means "current context" -->
        {/fieldsFromColumnDef}
      </tr>
    {/data.response}
    

    Finally, watch out-- your columnDef example is wrong! The capitalization doesn't match the names of the fields, so you'll get incorrect results. Once you fix that this example works, but I didn't change your question since that would alter its intent.