I'm struggling with json in twig. I want to include a static json file to my twig file and pass it to a twig include inside that.
I have my index twig file where I have my STATIC json file include and twig include:
{% set json %}
{% include "content.json" %}
{% endset %}
{% include '#partials/blocks/site-header.twig' with {json:json} %}
In My siteheader.twig I would like to render my navigation something like:
{% for headerNav in json %}
<a class="button button--nav" href="#">
{{headerNav.text}}
</a>
{% endfor %}
My content.json looks like this:
{
"headerNav":[
{
"text": "Link 1"
},
{
"text": "Link 2"
}
]
}
The whole point is that the siteheader should be able to render different links dependant on which json file i pass into it.
Related
I am trying to include a template file dynamically, but the variable does not appear to expand in the include declaration. How is this best done?
{% for file in files %}
{% include "{{ file }}.txt" %}
{% endfor %}
The error I am getting is:
jinja2.exceptions.TemplateNotFound: {{ file }}.txt
The below works for me.
I would like to clarify having a "." in jinja2 might create an issue so it would be better to pass the entire filename with extension to jinja2.
The usage of double quotes would not render the variable value so it would remain as it is like {{ file }}
The below works:
from jinja2 import Environment, FileSystemLoader
data = '''
{% for file in files.split(",") %}
{% include file %}
{% endfor %}
'''
template = Environment(loader=FileSystemLoader("templates/")).from_string(data)
msg = template.render(files="1.txt")
print(msg)
Output:
1.txt
I have an include that can have >1 buttons depending on what is passed in.
Currently I have the following in the include:
{% if include.buttons %}
{% for button in include.buttons %}
<a class="{{ button.classes }}" href="{{ button.url }}">{{ button.title }}</a>
{% endfor %}
{% endif %}
Then I am trying to pass in the following data:
{% assign buttons = '[{ "title": "button 1", "url": "https://#", "classes": "btn btn-transparent" }, { "title": "button 2", "url": "https://#", "classes": "btn btn-primary" }]' %}
{% include header.html
buttons=buttons
%}
What I can't work out is how to pass the data correctly to the include so that I may loop through it.
The problem is the assignment of the data as a array. In liquid you can not directly initialize arrays. A workaround is to play with split.
However, using jekyll you can provide arrays via data files. Simply put your buttons in a file, say _data\buttons.yml with:
postXX:
- button1:
- title: "button 1"
- url: "https://#"
- classes: "btn btn-transparent"
- button2:
- title: "button 2"
- url: "https://#"
- classes: "btn btn-primary"
Now you could put a reference in the yaml-header of your post/page like:
---
your other yaml options....
buttons: postXX
---
Finally, assign the buttons and include them as you did in your code.
{% assign buttons = site.data.buttons[page.buttons] %}
{% include header.html
buttons=buttons
%}
With Liquid, you can't create an array with a literal expression like {% assign myArray = ["one","two","three"] %}.
You can only :
create empty one : {% assign emptyArray = "" | split: "" %}
create one from string : {% assign myArray = "one two three" | split: " " %}
You can then manipulate your array :
add an element to array : push or shift (jekyll specific filters)
remove an element from array : pop or unshift (jekyll specific filters)
merge two arrays with concat
and so on ...
So, your array can only come from a liquid array manipulation or some datas contained in configuration, data file or page front matter.
I would like to use gulp and Nunjucks to generate multiple template files at once with varying content. These templates will all have the exact same layout, but pass in different variables for text/images.
I am able to successfully generate a single index.html file, but am unsure how to set this up for multiple files to be created at once. Here is a simplified version of what I have:
gulpfile.js
var nunjucks = require('gulp-nunjucks-render');
var data = require('gulp-data');
gulp.task('nunjucks', function () {
return gulp
.src('./src/layouts/**/*.+(html|nunjucks)')
.pipe(data(function () { return require('./src/data.json'); }))
.pipe(nunjucks({ path: ['./src/templates'] }))
.pipe(gulp.dest('./dist'));
});
layout.nunjucks
<head>
{% block title %} {% endblock %}
</head>
index.nunjucks
{% extends "layout.nunjucks" %}
{% block title %}
<title>{{ title }}</title>
{% endblock %}
data.json
{
"title": "DEFAULT"
}
What is the best way to alter this workflow to generate multiple files where each has a different title?
I've found that I can create multiple index.nunjucks files, but it looks like they all use the same data.json file. I also wouldn't want to make a separate JSON file for each.
Could I add an array to my data.json file to have Nunjucks loop through and create a separate file for each object found? Such as the following:
data.json
{
"files": [{
"title": "DEFAULT",
}, {
"title": "DEFAULT #2"
}]
}
Or is there a way to set variables within the index.nunjucks file without relying on storing them in JSON?
Found the way to do this: in each Nunjucks index file, I set a variable named email to the filename and updated my data.json file with a new object matching the filename with its own content.
default.nunjucks
{% set email = default %}
{% include "index.nunjucks" %}
test.nunjucks
{% set email = test %}
{% include "index.nunjucks" %}
index.nunjucks
{% extends "layout.nunjucks" %}
{% block title %}
<title>{{ email.title }}</title>
{% endblock %}
layout.nunjucks
<head>
{% block title %} {% endblock %}
</head>
data.json
{
"default":
{
"title": "TITLE"
},
"test":
{
"title": "TEST TITLE"
}
}
When compiled through gulp, two separate emails are created with their own title using the same template.
I am building a chatbot. There are few child templates like login.html, messages.html, transaction.html, etc. I want to append these templates in base.html dynamically. I am extending base.html in all these templates. My problem is only one template is rendered at a time. Is there any solution for appending these templates one after another? I have used {%include%} but it's a static approach. I need dynamic.
printer.py looks like -
#app.route('/respond', methods=['GET','POST'])
def respond_def():
message = request.form['message_input']
if message == "l":
return render_template('printer/login.html')
elif message == "t":
return render_template('printer/transactionID.html')
base.html looks like -
//some code here
<li>
{% block template %}{% endblock %}
</li>
//some code here
message.html looks like -
{% extends "base.html" %}
{% block template %}
<div> Message template called </div>
{% endblock %}
I resolved it.
I made a list of templates in printer.py and then appended those templates in base.html whenever user asked for it.
printer.py
dictionary = []
// append name of template in this whenever needed.
return render_template('printer/base.html', dictionary=dictionary)
base.html
{% for d in dicts %}
{% set template = 'printer/' + d + '.html' %}
// can add conditions for different templates
{% include template %}
{% endfor %}
I'm using Twig PatternLab.
I got a small issue with JSON and a Twig for loop.
Atom 00-h3-black.twig:
<h3 class="A-ChevronBlack">{{ text.chevron }}</h3>
Molecule 00-mastertile.twig:
<div class="M-DMasterTile">
<div class="image"></div>
<div class="content">
{% include "atoms-h3-black" %}
</div>
</div>
Organisms 00-default2.twig:
{% for post in default2 %}
{% include "molecules-mastertile" %}
{% endfor %}
And JSON inside Organism folder 00-default2.json
{
"default2" : [
{
"text" : {
"chevron" : "How to build a campfire",
"body" : "This is the body copy"
}
},
{
"text" : {
"chevron":"Lorem Ipsum",
"body" : "This is the body copy"
}
}
]
}
My expectation is for the "default2" to loop twice because I've got an array with 2 items in the JSON and push the JSON content. If I take the variables out of the JSON array it shows the changes(but obviously duplicated).
What am I doing wrong here?
I appreciate your help
include uses global scope and there is no variable text in it. Use include with syntax to pass variable into inner scope.
Your Organisms 00-default2.twig should look like this:
{% for post in default2 %}
{% include "molecules-mastertile" with {'text': post.text} %}
{% endfor %}