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.