Search code examples
javascriptnode.jshandlebars.jsexpress-handlebars

handlebars node.js issue with rendering table data


I have following data (array of objects) for my handle bar template. Please find the data below:

{
    "students": {
        "fees": {
            "others": [
                {
                    "Student Name": "Ashy",
                    "Term1": "$1,000.00",
                    "Term2": "$1,000.00",
                    "Total": "$2,000.00",
                },
                {
                    "Student Name": "Test",
                    "Term1": "$1,000.00",
                    "Total": "$2,000.00",
                }
            ],
        }
    }
}

Please note that the second object in the array above does not have the key Term2. Please find the handlebar template below:

{{#students}}
{{#fees}}
<table>
<thead>
   <tr>
     <td rowspan="1">Student Fees</td>
   </tr>
  <tr>
    {{#each others.[0]}}
      <th>{{@key}}</th>
    {{/each}}
  </tr>
</thead>
<tbody>
   {{#each others}}
    <tr>
        {{#each this}}
        <td>{{this}}</td>
      {{/each}}
    </tr>
  {{/each}}
</tbody>
</table>

{{/fees}}
{{/students}}

The output looks something like below:

enter image description here

Since value for Term2 does not exist for student named Test, data for Total column has moved to column for Term2. I want that if the student is not having any data for Term2 it should appear as blank and proper value should be associated with Total column. Basically the data should stick to the keys in the header above. Could anyone please let me know, how can I achieve that.

Thanks


Solution

  • In order to achieve your goal of getting consistent output, I think your best approach would be to ensure consistent input.

    Would you be able to add an empty string value to the second student at the key "Term2" and ensure that each student object contained the same set of keys ("Student Name", "Term1", "Term2", "Total")?

    That would be the most logical approach.

    If, for some reason, you cannot modify the student objects, then I think the next preferable solution would be to pass a columnsKeys array to your template. This array would define each column key to appear in your output and, when rendering students, we would loop through each column key for each student and perform a lookup to get the desired value.

    The object to add to your template data would look like:

    "columnKeys": [
      "Student Name",
      "Term1",
      "Term2",
      "Total"
    ]
    

    And your template would become:

    <table>
      <thead>
        <tr>
          <td rowspan="1">Student Fees</td>
        </tr>
        <tr>
          {{#each columnKeys as |columnKey|}}
            <th>{{columnKey}}</th>
          {{/each}}
        </tr>
      </thead>
      <tbody>
        {{#each students.fees.others as |student|}}
          <tr>
            {{#each ../columnKeys as |key|}}
              <td>{{lookup student key}}</td>
            {{/each}}
          </tr>
        {{/each}}
      </tbody>
    </table>
    

    I have created a fiddle for your reference.