Conditional forEach statement in Velocity Script | Community
Skip to main content
Jon_Wright
Level 4
May 1, 2019
Solved

Conditional forEach statement in Velocity Script

  • May 1, 2019
  • 3 replies
  • 11110 views

I've been using @Sanford Whiteman​'s excellent resource on using JSON in Velocity script but am stuck on how I'd go about only displaying certain records from the JSON.

For example in the following I only want to list the relevant values where {{lead.email domain}} = allProjects.domain. So anyone with a domain of company01.com would see the first 2 records listed, whereas company02.com would only see the last record (there will be about 50 - 100 records in the JSON eventually). Any pointers greatly appreciated!

#set( $allProjects = [

{

"domain": "Company01.com",

"category": {

"URL": "https://www.example.com/project1",

"companyName": "Company 01",

"name": "Example Project Name 01",

"participantType": "Champion"

}

},

{

"domain": "Company01.com",

"category": {

"URL": "https://www.example.com/project2",

"companyName": "Company 01",

"name": "Example Project Name 02",

"participantType": "Champion"

}

},

{

"domain": "Company02.com",

"category": {

"URL": "https://www.example.com/project1",

"companyName": "Company 02",

"name": "Example Project Name 01",

"participantType": "Champion"

}

}

}

] )

<p><br /></p>

<ul>

#foreach( ${allProjects.domain} in $allProjects )

<li>

<a href="${allProjects.category.URL}" target="_blank" id="">${allProjects.category.name}</a></li>

#end

</ul>

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by SanfordWhiteman

There's no built-in collection filtering w/predicates in Velocity. So you do a simple loop and move the matches into another collection:

#set( $domainProjects = [] )

#foreach( $project in $allProjects )

#if( $project.domain.equalsIgnoreCase($lead.emailDomain) )

#set( $void = $domainProjects.add($project) )

#end

#end

#foreach( $project in $domainProjects )

## this is your subset of matches

#end

Your {{lead.email domain}} token, when you check it off and drag it onto the Velocity canvas, isn't going to have a space in it (the Velocity $lead.property name isn't the same as the token name). So I've used $lead.emailDomain here.

3 replies

SanfordWhiteman
SanfordWhitemanAccepted solution
Level 10
May 1, 2019

There's no built-in collection filtering w/predicates in Velocity. So you do a simple loop and move the matches into another collection:

#set( $domainProjects = [] )

#foreach( $project in $allProjects )

#if( $project.domain.equalsIgnoreCase($lead.emailDomain) )

#set( $void = $domainProjects.add($project) )

#end

#end

#foreach( $project in $domainProjects )

## this is your subset of matches

#end

Your {{lead.email domain}} token, when you check it off and drag it onto the Velocity canvas, isn't going to have a space in it (the Velocity $lead.property name isn't the same as the token name). So I've used $lead.emailDomain here.

Level 6
May 1, 2019

Once you get the #foreach working, you may then be surprised by an obscure system behavior with links and #foreach loops.

If you are going to output a link from within a #foreach loop, you will probably need to add the class "mktNoTrack" to your link OR deploy a workaround. Otherwise, you'll potentially output a dead links.

Here's a resource that helped me understand what was going on when encountering this issue: https://blog.teknkl.com/multiple-marketo-tracked-links-in-velocity/

Jon_Wright
Level 4
May 2, 2019

Thanks for the tip, Mark! I am planning to output links so this is very helpful.

Jon_Wright
Level 4
May 2, 2019

Thank you, Sanford! What threw me for a bit in your script was the $project variable in the forEach statement:

#foreach( $project in $allProjects )

As I don't have any elements called $project in the JSON. So I can try and understand VTL a little bit more $project is declaring a variable for each record in the array?!

SanfordWhiteman
Level 10
May 2, 2019

Right.