Search code examples
javavelocity

How to iterate list items in Velocity and display intended result


Name    Attendance
Jon     01-01-2016
Jon     02-01-2016
Jon     03-01-2016
Doe     01-01-2016
Doe     02-01-2016
Chris   01-01-2016
Chris   02-01-2016
Chris   03-01-2016
Chris   04-01-2016

Assuming I have correctly populated the above list on the velocity context I could only think of a basic iteration on the list in velocity to retrieve results.

<tbody>
#foreach ($employee in $employees)
<tr>
    <td>$employee.name</td>
    <td>$employee.attendance</td>
</tr>
#end
</tbody>

I am not sure on how to group the results and also display a count next to each name. This is my desired output:

Jon(3)
01-01-2016
02-01-2016
03-01-2016

Doe(2)
01-01-2016
02-01-2016

Chris(4)
01-01-2016
02-01-2016
03-01-2016
04-01-2016

How do I achieve this output?


Solution

  • If you have a chance to create a nested list in your backing objects, I'd clearly prefer that to logic in the view. Besides it will be easier to implement it.

    But if it has to be that very list and you need to build your result in Velocity from that, I see two options, both including iterations. So, your approach is good - I can't see no other way.

    You could either transform the list in a first iteration and then do the output in another or use a nested iteration. The need for two iterations is caused by the counting you want to place prior the output of the dates.

    Here's a suggestion for a nested iteration:

    #set($name = "")
    #set($buffer = [])
    
    #foreach ($employee in $employees)
        #if($velocityCount == 1)
            #set($name = $employee.name)
        #end
    
        #if($name != $employee.name)
            <br>name($buffer.size())
            #foreach ($attendance in $buffer)
                <br>$attendance
            #end
            <br>&nbsp;
    
            #set($name = $employee.name)
            #set($buffer = [])
        #else
            #if($buffer.add($employee.attendance))#end
        #end
    #end
    

    Basically it's about adding the dates to an array and conducting the output whenever a the name changes. The size of the array is used for the count result.

    The line

    #if($buffer.add($employee.attendance))#end
    

    might look a little weird. The surrounding 'if'-clause is just there to keep Velocity from printing a true while adding a value to the array.

    Please note:
    I tested that only partly in Velocity 1.7, because I was way to lazy to rebuild that list. So, the result might not look exactly like the desired one, but it contains all the elements you need and the idea should be clear.