How to limit number of iterations when looping through object in nunjucks - html

I have a js object like this:
var data = [
{ src: "src1", name: "name 1" },
{ src: "src2", name: "name 2" },
{ src: "src3", name: "name 3" }
]
I am looping through it with Nunjucks:
{% for object in data %}
{{object.src}}
{% endfor %}
But I want to limit the number of iterations to 2.
How do I do that with Nunjucks?
I know there is a range option but I couldn't find how to use it in this case.

You could accomplish this a couple different ways:
A) Use loop.index0 special variable (Demo in Codepen)
Inside a for loop, you can use loop.index0 instead limit-var
{% for obj in data %}
{% if loop.index0 < 2 %}
{{obj.src}}: {{obj.name}}
{% endif %}
{% endfor %}
B) Add Custom Filter (Demo in Codepen)
But more readable is add custom filter limit and use it
var nunjucks = require('nunjucks');
var env = nunjucks.configure();
var data = [
{src: "src1", name: "name 1"},
{src: "src2", name: "name 2"},
{src: "src3", name: "name 3"}
];
env.addFilter('limit', function(arr, limit) {
return arr.slice(0, limit);
});
var res = nunjucks.renderString(`
{% for obj in data | limit(2) %}
{{obj.src}}: {{obj.name}}
{% endfor %}`,
{data}
);
console.log(res);
C) Use native slice() function (Demo in Codepen)
{% for obj in data.slice(0, 2) %}
{{obj.src}}: {{obj.name}}
{% endfor %}

Related

How can I fetch a value from a JSON dictionary?

I am trying to grab the value green from the below JSON data dictionary.
The API endpoint located at http://localhost:9200/api/status give the below data:
{
"name":"prod01",
"uuid":"3430c40-e786-4325-bc48-e0a096956000",
"version":{
"number":"7.17.0",
"build_hash":"60a9838d21b6420bbdb5a4d07099111b74c68ceb",
"build_number":46534,
"build_snapshot":false
},
"status":{
"overall":{
"since":"2023-02-13T22:47:05.381Z",
"state":"green",
"title":"Green",
"nickname":"Looking good",
"icon":"success",
"uiColor":"secondary"
},
"statuses":[
{
"id":"core:elasticsearch#7.17.0",
"message":"Elasticsearch is available",
"since":"2023-02-13T22:47:05.381Z",
"state":"green",
"icon":"success",
"uiColor":"secondary"
},
{
"id":"core:savedObjects#7.17.0",
"message":"SavedObjects service has completed migrations and is available",
"since":"2023-02-13T22:47:05.381Z",
"state":"green",
"icon":"success",
"uiColor":"secondary"
}
]
}
}
And the test.sls file doing the job is:
{% set json_data = salt.cp.get_url('http://localhost:9200/api/status', dest=None) | load_json %}
{% for key, value in json_data.items() %}
{% if value['state'] == 'green' %}
{{ key }}: {{ value }} (found)
{% else %}
{{ key }}: {{ value }}
{% endif %}
{% endfor %}
Executing it, I get the error:
Rendering SLS 'base:svr.salt.dev.test' failed: Jinja variable 'str object' has no attribute 'state'
You are looping on all the key-value pairs of the object json_data, with json_data.items(), so, you do not have a my_dictionary['state'] anymore, what you have is a key which will be state and its value will be green.
This said, your {"state": "green"} is not in the root of your dictionary, so you will never find any key-value pair matching what you need.
What you can do, though is:
{% if load_json.status.overall.state == 'green' -%}
state: {{ load_json.status.overall.nickname }}
{% endif %}
Which would yield:
state: Looking good

How to pass a concatenated string to HTML using Jekyll include?

I have to make a string of values separated by semicolons and pass this string to a script in HTML include to then parse and output the result.
My jekyll markdown page:
---
layout: page
title: Our team
permalink: /team
---
{% assign cfhandles=""%}
{% for person in site.data.team-handles %}
{{ cfhandles | append: person.handle }}
{{ cfhandles | append: ";" }}
{% endfor %}
{% include load-ratings.html cfhandles=cfhandles %}
My load-ratings.html:
<script>
let url = "https://codeforces.com/api/user.info?handles=";
let handles = "{{ include.cfhandles }}";
console.log(handles);
url = url + handles;
console.log(url);
async function load() {
let obj = await (await fetch(url)).json();
console.log(obj);
for (let cur_user of obj["result"]) {
let cur_handle = cur_user["handle"];
let user_rating = cur_user["rating"];
document.getElementById(cur_handle.toLowerCase()).innerHTML = "Рейтинг: " + user_rating;
}
}
load();
</script>
My team-handles.yml:
- handle: bob1
name: Bob
- handle: alice2
name: Alice
When I open the developer console, it shows me that in JS the handles variable is empty (but it shouldn't be like that). How do I pass the needed string to the file so it shows correctly?
I already tried using {%- -%} Liquid tags, but it didn't change the result.
Try this:
{% assign cfhandles=""%}
{% for person in site.data.team-handles %}
{% assign cfhandles = cfhandles | append: person.handle | append: ";" %}
{% endfor %}
{% include load-ratings.html cfhandles=cfhandles %}
The code basically assigns the new strings bob1; and alice2; to the existing variable.

loop through a for statement using an if/else with nunjucks and json

I'm trying to loop through a nested json file with nunjucks, give each object type a specific layout and sort all based on date.
So in my case I have two collections events and videos. Both collections will have an array of events and videos.
My file is named /content.json and structured as followed:
{
media: {
events: [
{
content_id: "1",
content_type: "event",
date: "01-11-2019",
etc: "etc"
},
{
content_id: "2",
content_type: "event",
date: "01-08-2019",
etc: "etc"
}
],
videos: [
{
content_id: "3",
content_type: "video",
date: "01-12-2019",
etc: "etc"
},
{
content_id: "4",
content_type: "video",
date: "01-09-2019",
etc: "etc"
}
]
}
}
I have tried to get the different object assigned with an if/else statement and then use a for loop to cycle through the array, but that has failed, see below:
{% for item in content.media %}
{% if item == events %}
{% for item in content.media.events %}
{% include "components/event.njk" %}
{% endfor %}
{% elif item == video %}
{% for item in content.media.videos %}
{% include "components/video.njk" %}
{% endfor %}
{% endif %}
{% endfor %}
I never got to try and sort all the content by date, but I have found:
{% for item in items|sort(attribute='date')%}
Can anyone guide me in right direction?
Thanks in advance.
AENM
This code outputs separated feeds by type of elements (event or video).
{% for event in content.media.events | sort(attribute = 'date') %}
{% include "components/event.njk" %}
{% endfor %}
{% for video in content.media.videos | sort(attribute = 'date') %}
{% include "components/video.njk" %}
{% endfor %}
If you need to output a mixed feed, you should join arrays to one and run trought it (fortunately each elements already have the type):
{% for item in [].concat(content.media.events, content.media.videos) | sort(attribute = 'date') %}
{% include "components/" + item.content_type + ".njk" %}
{% endfor %}
Aikon,
I got it now!!
It was another typo, you switched the media and events. (did you try to keep me sharp?! :-))
But that's why the concat didn't work!!
So this is the final working result:
{% for item in [].concat(media.content.events, media.content.videos) | sort(attribute = 'date') %}
{% include "components/" + item.type + ".njk" %}
{% endfor %}
Only the date is not in the correct order, but I think that has to with my grid setup.
Thanks for helping me out......

HTML If class paragraph contains string do

I am trying to edit code using Shopify and their Liquid templates. It should be simple and I've searched their site and online. Their suggestions have not provided me a solution.
This is the original line of code:
{% if settings.display_quickview_vendor %}
<p class="product-vendor"><label>Vendor</label><span></span></p>
{% endif %}
This statement will always be true, referencing the json file. Using the class="product-vendor" and the .js file, it inserts the vendor name with the Vendor label from product setup.
My goal is that when my vendor name is set to "--" (using a drop down in product setup) the vendor line of code will not be executed.
I've tried this
{% if settings.display_quickview_vendor %}
{% if product-vendor != "--" %}
<p class="product-vendor"><label>Vendor</label><span></span></p>
{% endif %}
{% endif %}
I've also replace the second if statement with the following.
{% if product.vendor != "--" %}
{% if product.vendor contains '--' %}
{% if product-vendor contains '--' %}
My experience is with C# and VBA. I have a feeling that I'm not fully understanding what it is that I need to be asking or searching for.
This is the .js file where the quickview window is called.
initQuickView: function() {
e(".quickview-button a").click(function() {
var i = e(this).attr("id");
return Shopify.getProduct(i, function(i) {
var a = e("#quickview-template").html();
e(".quick-view").html(a);
var o = e(".quick-view");
if (o.find(".product-title a").text(i.title), o.find(".product-title a").attr("href", i.url), o.find(".product-vendor span").length > 0 && o.find(".product-vendor span").text(i.vendor), o.find(".product-type span").length > 0 && o.find(".product-type span").text(i.type), o.find(".product-inventory span").length > 0) {
var n = i.variants[0].inventory_quantity;
o.find(".product-inventory span").text(n > 0 ? null != i.variants[0].inventory_management ? n + " in stock" : "Many in stock" : "Out of stock")
}
This is from the schema.json file.
{
"type": "checkbox",
"id": "display_quickview_vendor",
"label": "Display Vendor?",
"default": true
},
This is from the data.json file.
"display_quickview_vendor": true,

gulp-nunjucks-render and adding data from single file

How can I include data to gulp-nunjucks template from separate file?
//template/data/data.html
{% set
list = [
{
title: 'Item1'
},
{
title: 'Item2'
}
]
%}
This simple solution doesn't work.
{% include "data/json.html" %}
This should work if you use import instead of include, https://mozilla.github.io/nunjucks/templating.html#import
Try this (I used .njk extensions, but you can use .html, it won't matter):
//template/data/data.njk
{% set list = [
{
title: 'Item1'
},
{
title: 'Item2'
}] %}
And in the file where you want to use the {{ list }} variable:
//template/other-file.njk
{% from 'data/data.njk' import list %}
{{ list }}
Any top-level variables that are {% set %} or any macros that are defined are available via import.