Velocity Snippets #1: Sorts and seeks

The idea is for Snippets posts to be code-centric as opposed to blather-centric. Copypasta with minimal commentary… let's see how it goes!

ArrayLists in brief

As you advance with Velocity, you'll make heavy use of ArrayLists, that is, arrays of objects.

ArrayLists are created automatically by Marketo when you access Custom Objects (as <CustomObjectName>List), and you can also create your own using the simple literal syntax you see throughout my code:

#set( $myList = [ 1, 11, 22 ] )
#set( $myOtherList = [
  {
    "id" : 123,
    "prop1" : "apple"
  },
  {
    "id" : 456,
    "prop2" : "orange"
  }
] )

Coming from another language, you might think $myList is some kind of simpler array type while $myOtherList is more like an “array of objects.” In Velocity they're both ArrayLists: doesn't matter that the first looks like only scalars (integers). This is good because it means you can use the same methods to access them.

Sorting ArrayLists by primary properties (think timestamps) and grabbing the most important item are both things you'll want to do — trust me!

The sample ArrayList

All examples use this sample ArrayList, $productInterestList:

[
  {
    "ProductName" : "Oranges",
    "ProductId" : "123",
    "SignupDate" : "2017-05-04"
  },
  {
    "ProductName" : "Red Apples",
    "ProductId" : "679",
    "SignupDate" : "2017-02-05"
  },
  {
    "ProductName" : "Golden Apples",
    "ProductId" : "678",
    "SignupDate" : "2017-02-02"
  },
  {
    "ProductName" : "Raisins",
    "ProductId" : "456",
    "SignupDate" : "2017-05-01"
  }
]

Seeking the first and last item

#if( $ProductInterestList && !$ProductInterestListintmentList.isEmpty() )
#set( $firstItem = $ProductInterestList[0] )
#set( $lastItem = $ProductInterestList[$math.sub($ProductInterestList.size(),1)] )
#end
First Item: ${firstItem}
Last Item: ${lastItem}
  • Standard pattern you'd do in any language without an explicit getLast() method.
  • Literal subtraction (minus sign -) shouldn't be done in VTL because it's too easy to break the parser. Use $math.sub() or $math.add() instead.
  • Uses real index order. No reordering by item contents/properties.

Reordering by item contents

#set( $byProductIdAsc = $sorter.sort($ProductInterestList,["ProductId"]) )
#set( $byProductIdDescThenDateAsc = $sorter.sort($ProductInterestList,["ProductId:desc","SignupDate"]) )
#set( $bySignupDateAscThenIdDesc = $sorter.sort($ProductInterestList,["SignupDate","ProductId:desc"]) )
  • $sorter.sort can sort by inner properties (properties of the objects in a list).
  • Default sort is ascending but can be specified as :asc or :desc.
  • Sort by a datetime field to put your site-specific “most important” object at the top or bottom of new list, then use first/last code above to get the item.

Reversing a list

#set( $reversedList = [] )
#foreach( $itm in $ProductInterestList )
#set( $temp = $reversedList.add( 0, $itm ) )
#end
  • Adds all items to the head (index 0) of a new ArrayList, reversing the order.
  • Like JavaScript's Array.prototype.reverse, which is a built-in method.
  • Useful when a list is otherwise correctly ordered but you want to display it in reverse (like if you know items were appended chronologically, but they don't have an explicit timestamp field).

Displaying one property from each member of a list

$display.list( $byProductIdAsc, "\u000A", "\u000A", "ProductName" )

Output:

Oranges
Raisins
Golden Apples
Red Apples
  • Seeks and displays only the inner property ProductName.
  • "\u000A" is a newline (VTL doesn't use "\n"). In HTML you'd want "<br>" instead.
Coming soon…

Next up are snippets for numbers and currency formatting.