MailJet nested loops - loops

we are building our emails with mailJet which works fine so far. Our current problem is, that we would like to have a loop within a loop within a loop (so nested loops) the first loop works fine, and also the second inner loop is working fine, but the third one isn't working anymore:
{% for trip in var:trips %}
{{trip.id}}
{% for tripSegment in trip.tripSegments %}
{% for tripBreak in tripSegment.breaks %}
{{tripBreak.duration}}
{% endfor %}
{% endfor %}
Distance: {{trip.totalDistance}} km
{% endfor %}
This is in our template. If I remove the inner loop with the breaks, everything is fine.
If I enable the Template Error Reporting I get the following message:
X-MJ-ErrorMessage: "tripSegment.breaks" is not an array value
but if I try to print it with {{tripSegment.breaks}} I get the message:
X-MJ-ErrorMessage: Array values cannot be printed: tripSegment.breaks
and the field is definetly an array, like the trips or tripSegments, so basically it should work.
What am I doing wrong for nested loops in MailJet?
Edit:
My Object Structure, I send to Mailjet looks like this:
"Vars": {
"trips": [
"id": 1,
"tripSegments":[
{
"id":2,
"distance": 100,
"breaks":[
{
"duration":15
},{
"duration":20
}
]
},{
"id":3,
"distance": 200,
"breaks":[
{
"duration":10
},{
"duration":30
}
]
},{
"id":4,
"distance": 200,
"breaks":[
]
},
]
]
}

If you would like to loop on tripSegment.breaks, it should be represented as an array and not as an object.
I managed to create a sample which works for me with the same values you use.
'Vars' => [
"trips"=>[
'trips1' =>[
'id'=> 123,
'totalDistance'=> 10,
'tripSegments' => [
['breaks' =>[['duration'=>1],['duration'=> 2]]],
['breaks' =>[['duration'=>1],['duration'=> 2]]],
['breaks' =>[['duration'=>1],['duration'=> 2]]]
]
]
]
]

I find this has nothing to with the WYSIWYG Editor, remains a bug in Mailjet's templating language, and is easily reproducible. Use Postman or other API testing tool to send the following JSON to the send endpoint (make sure you add your API key credentials via Basic Auth):
POST https://api.mailjet.com/v3/send
{
"FromEmail": "me#example.com",
"FromName": "Me",
"Subject": "Test",
"MJ-TemplateLanguage": true,
"MJ-TemplateErrorReporting": "me#example.com",
"MJ-TemplateErrorDeliver": "deliver",
"Recipients": [
{ "Email": "me#example.com" }
],
"Html-part": "<ul>{% for project in var:commissions.projects %}<li>{{project.name}}</li>{% endfor %}</ul>",
"Vars": {
"commissions": { "total": "235,000", "projects": [] }
}
}
You'll get an error report via email back to you with the content No value for "commissions.projects" instead of it simply passing through the loop silently.

As we were in discussion with the MailJet Support [1], it turns out that there is a bug in the WYSIWYG editor of MailJet.
the multiple nested loops work, if you use them within a HTML Block and not directly in the WYSIWYG Editor.
They are working on that.
[1] https://app.mailjet.com/support/ticket/21e111b3be8630214cc082845f6cf976

Related

Liquid: Check For Specific Value In Array Before Moving On (Braze)

How are you all?
I am trying to get a liquid use case to check an array for a certain value before moving on.
The scenario. I want the liquid to look at a shopping cart (an array of products) and check to see if it has certain items. It will have to look at the product IDs in the array to figure out if the "right" product(s) are in the shopping cart. To put it another way, the liquid will have to go through all the product IDs and see if any of them match the required ID(s).
The data:
products": [
{
"Id": 2075302363194",
"name": "Space Ship",
"brand": "Supermake",
"category": "Space"
},
{
"Id": "17405302866504",
"name": "Electric Guitar",
"brand": "Bling Music",
"category": "Music"
},
{
"Id": "4531514605626",
"name": "Rugby Ball",
"brand": "Rubberright",
"category": "Sport"
}
]
I haven't found what I'm looking for yet, but this seems to be a good start, for what it's worth.
{% assign products = {{canvas_entry_properties.${products}}} %}
{% for item in products %}
{% unless item.Id contains "1740530286650" %}
There are no items with a product ID of 1740530286650 in this shopping cart.
{% endunless %}
{% endfor %}
Note that the "canvas_entry_properties.${products}" is just how one would fetch the product array data within Braze (braze.com).
I would be very grateful for any help.

How to query site data in hugo using where

In a hugo template how can I do a lookup on .Site.Data. Assuming I have a data structure like this:
{
"my-blog-post": {
"Version": 21,
"Revision": 0,
"Code": "my-blog-post",
"Name": "My Blog Post",
"Parent": "the-parent-post"
},
"another-post": {
"Version": 21,
"Revision": 0,
"Code": "another-post",
"Name": "Another Post",
"Parent": "the-parent-post"
}
}
Inside the detail page for a blog post, I would like to get the list of all the posts that have the current post as the parent. Basically I would like to query posts that have "the-parent-post" as the value of Parent field.
I can achieve this using range but I need to get them using where.
I experimented with expressions like this but no joy.
{{$child_posts := where (where .Site.Data "Section" "blog") "Parent" "the-parent-post" }}
I can do this:
{{$posts := where $site.Pages "Section" "blog"}}
{{ range sort $posts "Name" "asc" }}
{{ $post := . }}
{{if eq $post.parent $currentPage.Code}}
...Do something...
{{end}}
{{end}}
But it is not ideal and not what I need.
Thanks in advance.
Your are trying to range through a map of maps. You need an array of maps.
https://discourse.gohugo.io/t/filtering-data-in-json-using-where/35287/2

Logic Apps liquid template ask

I am a complete newcomer to Liquid, started playing with it a few hours ago.
i am trying to parse a JSON and extract certain key value pairs out of it, yet i am not successful at all. the JSON is outputed from Azure Form Recognizer, and i am trying to do a Liquid json 2 json in Logic Apps.
the JSON looks like this
{
"status": "success",
"pages": [
{
"number": 1,
"keyValuePairs": [
{
"key": [
{
"text": "Page No:",
"boundingBox": [
507.4
]
}
],
"value": [
{
"text": "1",
"boundingBox": [
586.8
],
"confidence": 1.0
}
]
},
....
...
what i am looking for is to loop through the keyValuePairs array, and then pull the "text" element from the "key" array, and the "text"+"confidence" element from the "value"array.
Could you please help me in understanding the approach here? I tried something like this, but the array comes back empty
{
"results":[
{% for kvp in content.keyValuePairs %}
{% for mykey in kvp.key %}
"thiskey":"{{mykey.text}}
{%- endfor -%}
{% for myval in kvp.value %}
"thisvalue":{{myval.text}}
"thisconfidence":{{myval.confidence}}
{%- endfor -%}
{%- endfor -%}
]
}
And second question: what's the best approach for debugging Liquid, so i can see where i am getting it wrong and adjust?
Thank you!
According to the sample of json data and the liquid template you provided, I know there are more than one object under the property keyValuePairs in your json data. So I think using "Parse JSON" action is not a good solution for it, we'd better use liquid template as you mentioned in your question. But I'm confused about that if there are more than one object under the property pages in your json data ?
Now I assume the json data just has one object under the property pages and provide the solution of liquid template for your reference (If the json data has more than one object under the property pages, please provide some more details of your requirements and I will modify my solution).
I assume your json data like below:
{
"status": "success",
"pages": [
{
"number": 1,
"keyValuePairs": [
{
"key": [
{
"text": "Page No:",
"boundingBox": [
507.4
]
}
],
"value": [
{
"text": "1",
"boundingBox": [
586.8
],
"confidence": 1.0
}
]
},
{
"key": [
{
"text": "Page No:",
"boundingBox": [
507.4
]
}
],
"value": [
{
"text": "2",
"boundingBox": [
586.8
],
"confidence": 2.0
}
]
}
]
}
]
}
1. We need to get the object under the property pages and put it in the "content" of "Transform JSON to JSON" action. We can parse the whole json data(with "Parse JSON" action) first and do something like below:
2. Upload the liquid template to integration account, please refer to my liquid template:
{
"results":[
{% for kvp in content.keyValuePairs %}
{%- if forloop.Last == true -%}
{
{% for mykey in kvp.key %}
"thiskey": "{{mykey.text}}",
{%- endfor -%}
{% for myval in kvp.value %}
"thisvalue": "{{myval.text}}",
"thisconfidence": "{{myval.confidence}}"
{%- endfor -%}
}
{%- else -%}
{
{% for mykey in kvp.key %}
"thiskey": "{{mykey.text}}",
{%- endfor -%}
{% for myval in kvp.value %}
"thisvalue": "{{myval.text}}",
"thisconfidence": "{{myval.confidence}}"
{%- endfor -%}
},
{%- endif -%}
{%- endfor -%}
]
}
3. After running this logic, we can get the result as:
{
"results": [
{
"thiskey": "Page No:",
"thisvalue": "1",
"thisconfidence": "1"
},
{
"thiskey": "Page No:",
"thisvalue": "2",
"thisconfidence": "2"
}
]
}
Something you need to be aware of:
Since we put the object under the property pages to the content of "Transform JSON to JSON" action, so the content in the liquid template represents it.
In liquid template, we need to be careful about the comma character, so I use {%- if forloop.Last == true -%} to judge if it is the last object in the loop, and then judge if we need to add the comma character.
For your second question about what's the best approach for debugging Liquid ?, unfortunately I think we can just complete the liquid template and upload to the integration account, then we can see the result. I don't know if there is a way for us to debug it easily.
Hope it helps~
I have tried to design workflow using your sample JSON payload.
I have parsed the JSON schema and extracted the required values from it.
Since your JSON payload is a bit complex, we need to use Logic App Expressions to extract the value out of it.
Payload I used:
{
"status": "success",
"pages": [{
"number": 1,
"keyValuePairs": [{
"key": [{
"text": "Page No:",
"boundingBox": [
507.4
]
}],
"value": [{
"text": "1",
"boundingBox": [
586.8
],
"confidence": 1.0
}]
},
"null"
]
}]
}
Once you get the JSON output from the upstream actions, you have to parse it.
Now, Initialize a couple of variables to get the required value from the parsed JSON.
Expression to be used in the first variable: concat(body('Parse_JSON')?['pages'][0]?['keyValuePairs'][0]?['key'][0]?['text'],body('Parse_JSON')?['pages'][0]?['keyValuePairs'][0]?['value'][0]?['text'])
Expression to be used in the second variable: body('Parse_JSON')?['pages'][0]?['keyValuePairs'][0]?['value'][0]?['confidence']
Finally, the logic apps after your Form Recognizor will look something like this:
I hope it helps!

How do I hide the square brackets in my template expressions?

I have a simple JSON object in my models
whitelist = [
{
"name": "Whitelist #1",
"permissions": [
"production_sdk",
"source_sdk",
"service"
],
},
{
"name": "Whitelist #2",
"permissions": [
"production_sdk",
"service"
],
},
{
"name": "Whitelist #3",
"permissions": [
"production_sdk",
"source_sdk"
],
}
]
In my html I have {{ whitelist.permissions }}, but the HTML displays the values with brackets - ['production_sdk', 'source_sdk'].
How can I display the HTML so that there are no brackets?
whitelist.permissions is an array, how do you want that to be displayed in your html? You should probably create a simple filter that takes an array and outputs what you want, but you could just change your html to do this to get a comma-separated list:
{{ whitelist.permissions.join(', ') }}
Another option, especially if you want to style each permission, is to use ng-repeat and html elements:
<span ng-repeat="permission in whitelist.permissions"><span ng-if="$index != 0">, </span>{{ permission }}</span>

Angular ng-model-options for a Select List within ng-repeat

I am struggling to get my head around this.
In my JSON I have:
"TargetMeasures":
[{
"Name": "Electricity",
"AnnualTarget_MeasureId": 1,
"SelectList": [
{
"Text": "kWh",
"Value": "1",
"Selected": false
},
{
"Text": "mmBTU",
"Value": "2",
"Selected": false
}
],
}]
I have a repeater where I want a select list to appear:
<div ng-repeat="measure in TargetMeasures">
<select name="{{ measure.Name }}_MeasureId"
data-ng-model="measure.AnnualTarget_MeasureId"
data-ng-model-options="XXX"></select>
</div>
I can't get my head around what I would need to put in XXX to ensure I get the right tags in my output.
I have tried reading the documentation and some other questions on here, and so far the best I could come up with is "Text for Value in measure.SelectList".
This gives me: "Error: [$parse:syntax] Syntax Error: Token 'for' is an unexpected token at column 6 of the expression"
Your directive name is wrong, it should be ng-options="Text for Value in measures.SelectList"

Resources