Search code examples
htmlxmltemplatesvelocityhtml-templates

How to populate a table in a HTML xml template


I am working on a task where I need to add tables of data to our email templates. I am working with a Scala backend, and using Velocity to add the context to our emails. This table has 3 columns for 3 different work types: In-office, working remotely, and Not working.

Each column should contain the names of employees whose work type matches the column on a given day. The problem I am having, is I don't know how to fill this table in the format we want. An example of the table would be:

In-office | Working remotely | Not working
__________________________________________

Bob S     | Helen R          | Nobody
John D    | Samuel C         |
Harry F  

So my problem is, tables tend to be filled row-by-row, if there is a way I can populate this table column-by-column then I am sure I could figure it out. But, in my xml document where my HTML template is defined, I currently have the following:

<table id="demo">
   <tr><th> In-office</th><th>Working remotely</th><th>Not working</th></tr>
      #foreach( $teamDay in $scheduleDaysForTeam )
      #if($teamDay.date == $day.date)
      <tr><td></td><td></td><td></td></tr>
</table>

And yes, I know that this is not perhaps the way I should be tackling this task, but I am lost as to how I can achieve it.

For context, scheduleDaysForTeam is of type Array[util.Hashtable[String, String]], and $day is from a separate Array[util.Hashtable[String, String]].


Solution

  • You need to do a calculation prior to displaying the table. Something like:

    ## some working variables
    #set( $modes = [ 'off', 'rem', 'nw' ] )
    #set( $columns = { 'off': [], 'rem': [], 'nw': [] } )
    
    ## fill $columns
    #foreach( $teamDay in $scheduleDaysForTeam )
      #if( $teamDay.date == $day.date )
        #set( $junk = $colums[$teamDay.mode].addAll($teamDay.members) )
      #end
    #end
    
    ## get the maximum length
    #set( $max = 0 )
    #foreach( $mode in $modes )
      #if( $columns[$mode].size() > $max )
        #set( $max = $columns.get($mode).size() )
      #end
    #end
    
    ## display the result
    <table id="demo">
       <tr><th> In-office</th><th>Working remotely</th><th>Not working</th></tr>
    #foreach( $line in [0..$max] )
      <tr>
      #foreach( $mode in $modes )
        <td>
        #if( $columns[$mode].size() > $foreach.index ​)
          $columns[$mode][$foreach.index]
        #elseif( $foreach.index == 0)
          Nobody
        #end
        </td>
      #end
      </tr>
    #end
    
    
    #foreach( $teamDay in $scheduleDaysForTeam )
          #if($teamDay.date == $day.date)
          <tr><td></td><td></td><td></td></tr>
    </table>
    

    Of course, you'd better prepare this calculation upstream on the Java side if you have access to it, to keep your template clean.