Store result of Jinja filter - set

The basics of what I am trying to do is to use the 'random' filter to choose a random item from my list but then I want to use that randomly chosen item in multiple locations.
How do I set the result of a filter to a variable that I can use in multiple locations.
If I call the 'random' filter multiple times there is little chance they will be the same.
Essentially what I want to do:
{% set image = {{ images | random }} %}
obviously this doesnt work.

Use the filter without {{ }} delimiters.
{% set image = images|random %}
Jinja stores globals and filters in two different namespaces (dictionaries), which prevents them from being used interchangeably.

It's not working on loop, I had used this code:
{% set result = result | replace('x','y') %}

Related

Errors with nesting macros and passing a collection through them? Using Eleventy with Nunjucks

Somewhat of a more advanced question here... is it possible to pass a collection down through a few macros? For example, I have a blog posts section:
{% from "components/switchers/topCoupons.njk" import topBonuses %}
{{ topCoupons(
title = "Top Coupons",
blurb = "some body text content",
posts = collections.coupon
) }}
Then within the posts macro, I have a slider macro:
{% from "components/sliders/generalSlider.njk" import generalSlider %}
{{ generalSlider(
slides = posts
) }}
Then within the slider macro, I have a card macro:
{%- for slide in slides -%}
{% from "components/cards/card.njk" import card %}
{{ card(
title = posts
) }}
{%- endfor -%}
At the moment it is not working but I'm wondering how could I approach this situation and whether Eleventy and Nunjucks even offer this type of functionality, what the solution would be, or if I'm better off using another SSG that would have this kind of infrastructure?
At the moment, it is throwing this error when trying to compile:
[eleventy:dev] `TemplateContentRenderError` was thrown
[eleventy:dev] > (./src/index.njk)
[eleventy:dev] TypeError: Converting circular structure to JSON
Any and all insight is very much appreciated. Thanks :)
There's nothing inherently wrong with passing Eleventy collections through nested macros since a collection is just a regular JavaScript array. The issue arises depending on how you're using the collection inside Nunjucks since the collections object is a circular structure.
You can try this yourself by passing a collection into a macro and only accessing individual properties in the collection.
{# include.njk #}
{% macro navigation(data) %}
<ol>
{%- for page in data -%}
<li>
{{ page.data.title }}
</li>
{%- endfor -%}
</ol>
{% endmacro %}
{{ navigation(collections.all) }}
This setup works perfectly fine even with more macro nesting. The error you're running into comes from doing something like using the dump filter.
{# include.njk #}
{{ collections.all | dump }}
Since I don't know what your macros are doing, I'm not sure what is exactly causing the error to be thrown, but you might want to look for things that might be JSON.stringifying the collections object. Depending on your use case, you might have to manually parse the object yourself, find an external library, or only use the fields you need. Creating custom Eleventy filters may help.

Sorting in Jekyll / liquid code based on two columns

In my code I am trying to read about 100 yml files and create an html table. The problem I am facing is I am unable to sort based on two columns. The column names are vendor and name.
I need to first sort on Vendor and then name.
It sorts on one columns only the vendor column and ignore the next column name.. All the column names are correct.
This is the code.
{% assign devices = "" | split: " " %}
{% for device in site.data.devices %}
{% assign devices = devices | push: device[1] %}
{% endfor %}
{% assign sorted = devices | sort_natural: 'name' | sort_natural: 'vendor' %}
{% assign lastVendor = "" %}
{% assign nbDevices = 0 %}
{%- for device in sorted %}
{%- assign nbDevices = nbDevices | plus:'1' %}
{%- assign lastVendor = device.vendor %}`
Here i start creating the table which gets filled with values from the yml files.
The table when created is sorted on only one column. Either vendor or name.
Tried group_by as suggested here but then no values show up in the table not sure why.
Tried sort and sort_natural both the effect is the same.
Any suggestions as to what I am doing wrong here.
Finally figured out why the code was not working.
We were building our jekyll site using docker. The docker image was outdated.
A build using just bundle exec jekyll serve resolved the issue !!
Now need to update the bundler and gems....still figuring out what all gets updated and will post here in case it helps anyone.

Ansible, how to use jinja2 template to access specific value in a list

New to Jinja2 templating
I can iterate over a list using a for conditional which is simple enough but i am trying to do the below...
I have a variable that contains a un-ordered lists of values which are group names. I would like to access the group_names lists/variable and check if a specific item in this list exists and then perform an action if that value is found.
group_names: [ "groupname1", "groupname2", "groupname3", "groupname4"]
Sounds like you want:
{% if "somevalue" in group_names %}
whatever stuff
{% endif %}
http://jinja.pocoo.org/docs/2.9/templates/

and/or on a where_exp expression on Jekyll

I'm trying to use where_exp to filter Jekyll pages based on two categories using or operator:
{% assign sortedPages = site.pages | sort:"date" | reverse | where_exp:"page","page.categories contains 'design-pattern'" %}
But I'm getting this error:
Expected end_of_string but found pipe
Ar or/and operators really supported? I can't figure out how to filter pages using where_exp as shown in my code snippet.
I've managed to solve my issue with some workarounds... It's not a very elegant solution, but as Jekyll isn't about creating actual software architecture... For now, it works flawlessly:
{% assign patterns = "" | split,"" %}
{% for page in site.pages %}
{% if page.categories contains "design-pattern" or page.categories contains "anti-pattern" %}
{% assign patterns = patterns | push:page %}
{% endif %}
{% endfor %}
{% assign sortedPages = patterns | sort:"date" | reverse %}
I create an empty array.
I loop over all pages and I filter them by two possible categories.
I push pages that fulfill the whole condition.
Once I get the filtered page array, I sort and reverse it.
I was unable to replicate the error message you included with your original question. However, as far as filtering based on multiple conditions goes, it is supported. You can also put all of your filters together. The result is much cleaner code 😊
Example
If one wants to set a variable named "sortedPages" equal to "site.pages", but with the following filters:
Sort by date
Sort in reverse order
Only include a page if it has design-pattern and/or anti-pattern as a category
they can do so with the following one-liner:
{% assign sortedPages = site.pages | sort:"date" | reverse | where_exp: "item", "item.categories contains 'design-pattern' or item.categories contains 'anti-pattern'" %}
Answer as multiple lines
Splitting up statements across multiple lines is also supported. Doing so can sometimes improve readability:
{%
assign sortedPages = site.pages
| sort:"date"
| reverse
| where_exp: "item", "item.categories contains 'design-pattern' or item.categories contains 'anti-pattern'"
%}

how to use variable to pass filter name in jinja2 templates

I have defined some filters and use it very often. I need to do some A/B tests and for this in some situations some of filters should work in different way.
Easiest way to do this would be create a variable in template which store a filter name. something like this:
{% set filter_name = 'some_name' %}
{{ my_value|filter_name }}
But when I try this, I get an error:
TemplateAssertionError: no filter named 'filter_name'
Please help me to find a solution.
By doing {% set filter_name = 'some_name' %}, you have create a string variable named "filter_name". You should create a filter which takes one more argument on basis of which it decides what to do.
{% set filter_name = 'some_name' %}
{{ my_value|myfilter(filter_name) }}
def myfilter(value, filtername):
if(filtername is 'twice')
return value*2
else
.....

Resources