I've recently been trying to get to grips with nunjucks, I've used handlebars before so the learning curve hasn't been that bad. However there is one thing I can't seem to get working:
I've got a JSON file which has the following data in it:
"contentIntro" : {
"componentClass" : "c-global-header",
"title" : "Welcome Firstname Surname,",
"subtitle" : "New applications:",
"bodyCopy" : "You can create, edit and save the draft application as many times as you need before submitting it for assessment.",
"ctaType" : "text",
"ctaText" : "View the list",
"ctaURL" : "#"
}
This exists in a JSON file which includes other page elements but it's only the contentIntro context I'm interested in.
If I include a partial like this:
{% include "components/c-headed-text.nunjucks" %}
then I can access the JSON data using dot notation within that partial (eg {{ contentIntro.title }}), however this isn't very flexible and it precludes me having more than one of the same partial type on the page.
Ideally what I'd want to do is import the partial like this:
{% import "components/c-headed-text.nunjucks" as contentIntro %}
and then in the template I can just access the JSON data using {{ title }} as it will already know the context from the import.
Annoyingly though it doesn't work and I can't see why. The Jinja2 documentation seems to suggest it would but I can't get it to work using Nunjucks, is this even possible?
Edit: I should also add that the templates are being prerendered in gulp so the end result is just flat HTML.
Ok I've found a way around it. it's not as clean as I'd like but it does the job.
I just a normal include statement:
{% include "components/c-headed-text.nunjucks" %}
but above it a set a variable as follows:
{% set context = contentIntro %}
Then inside the partial I can just use {{ context.title }} and it works like a charm!
Related
Let's say I have a bunch of _data files that I use to create a list for specific pages. All of the pages that have these lists have a custom front matter variable of pageName. The value of pageName just so happens to match the _data file with the list.
Rather than pasting the html blocks of code into each page, I'd like to use an include to pull in a generic block of html. To do that, the include has to be dynamic or contain liquid markup to become dynamic.
That might be more context than you need, but my question boils down to this, is something like this possible:
{% for item in site.data.{{page.pageName}} %}
{{ item.label }}
{% endfor %}
Unless I'm missing something, this doesn't work so I'm wanting to know if there's a way of achieving similar functionality.
I found this similar question, but it doesn't seem to answer whether it can be used to access a page variable to build a file name.
You can use the bracket notation like this :
{% for item in site.data[page.pageName] %}
I hope someone can assist me on this issue.
I am pulling details from a database to display on a twig template (using Symfony2) but the way in which it is saved in the db makes it difficult to interpret the HTML.
Basically, the HTML tags are already translated as entities in the table, e.g.:
<p>Bach Flower Crab Apple Remedy: the "cleansing" Remedy can be used both internally and externally </p><p><strong>
And so on. I have researched the rendering options in twig and tried the following (based on me rendering a loop of product descriptions):
{% set strategy = 'html' %}
{% autoescape 'html' %}
{{ product.description|escape('html')|raw }}
{% endautoescape %}
and also just:
{{ product.description|raw }}
The first method just echoes the existing content (as entities) and the second method just renders the HTML tags to the page as follows:
<p>Bach Flower Crab Apple Remedy: the "cleansing" Remedy can be used both internally and externally.</p><p><strong>...
So, as you can see, I cannot find a way to actually interpret the HTML tags in order to display the description as it should be.
Is there a way to do this? I can't do it in the PHP as all it's doing is sending an object to the template which is looped through:
public function showAction(Request $request, $store_id=0)
{
$max = 1000;
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
$products = $repository->getProductsByStoreId($store_id,$max);
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$products,
$request->query->get('page', 1),
20
);
$return['products'] = $pagination;
$return['categories'] = $this->getCategories();
return $this->render('AppBundle:tables:productstable.html.twig', $return);
}
Your core issue is that you do not have HTML in your database to begin with. At best Twig could be outputting some HTML entities, which will render visibly as "<p>...", and at "worst" Twig will escape the text to render it accurately as it actually is, which is "<p>...". Expecting Twig to output actual HTML which will render a paragraph is unrealistic, since that's not what your original data contains at all.
You'll have to HTML-decode that text in PHP first, and then output it in Twig with ..|raw. raw means that Twig will output it as is without further escaping it. Since it's nonsense to get the data from the database to then html_entity_decode it, you need to fix your data input here! Don't HTML encode data which is going into the database, it serves no purpose.
I think you have to write custom escaper plugin to decode html entities and use it like this:
{{ product.description|myawesomehtmlentitiesdecoder|raw }}
http://twig.sensiolabs.org/doc/filters/escape.html#custom-escapers for reference.
But generally, it's better to store HTML in database and then apply needed security filters on output.
Ok, so let's say I use listdir to make an object of pictures, their names, sizes and their file names. The object is parsed so that each file name is item.values()[0]['item']. I am trying to do:
{% for item in banners %}
<h3>{{item.keys()[0]}} size {{item.values()[0]['size']}}:</h3>
<div>
<img src="{{url_for( 'static', filename= 'banners/{{item.values()[0]["item"]}}' )}}" />
</div>
{% endfor %}
But it is not working, replacing {{item.values()[0]["item"]}} with a specific file name is working and I can see that the file names are in the object, yet it will not generate the image, instead it says it failed to load the given url and the urls are weird, for example one shows up like:
<img src="/static/banners/%7B%7Bitem.values%28%29%5B0%5D%5B%22item%22%5D%7D%7D%7Csafe">
Something to do with it interpreting the characters as is instead of what they are to represent, but I cannot figure out the syntax. Thanks.
You are already in a {{ }} block, so nesting more of those is incorrect. I think it should be something in the lines of :
filename = 'banners/' + item.values()[0]["item"]
I need to provide page content reference list (it should contain references on sections on page).
The only way which I can see is to use page.content and parse it, but I stumbled on problem with data evaluation. For example I can pull out this string from page.content: {{site.data.sdk.language}} SDK but there is no way to make jekyll process it, it outputs as is.
Also I want to make it possible to create cross-pages links (on specific section on page, but that link generated by another inclusion and doesn't persist in page.content in HTML form).
Is there any way to make it evaluate values from page.content?
P.S. I'm including piece of code which should build page content and return HTML with list (so there is no recursions).
P.P.S. I can't use submodules, because I need to run this pages on github pages.
Thanks.
Shouldn't {{ site.data.sdk.language | strip_html }} do it? I don't know, most probably I didn't understand the problem. Can you elaborate more? Maybe provide a link to a post you're referring to?
Thinking about the similar
{% assign title = site.data.sdk.language %}
which is a stock Liquid tag and does the job well, so instead of
{% section title={{site.data.sdk.language}} %}
write your code as
{% section title = site.data.sdk.language %}
The key here is that once you enter {%, you're in Liquid. Don't expect Liquid to go "Inception" all over itself. {{ is just a shorthand for "print this to output", but an parameter passing is not output, it's just reading a variable.
You should be able to also go wild and do:
{% section title = site.data.sdk.language | capitalize %}
For more re-read the docs: https://github.com/Shopify/liquid/wiki/Liquid-for-Designers
Im using django-profiles. In my profile_detail template I know that I will receive a profile variable.
I want to make a custom tag that gets the content per user via user id. Like this:
{% get_user_content book.review profile.user.id as review_list %}
However, when my parser runs It seems like profile.user.id was not transformed to an id number and throws an exception.
I can verify that my custom tag works by changing profile.user.id to say 1 for admin.
{% get_user_content book.review 1 as review_list %}
Has anyone deals with it before? What did you do?
Template tags never translate arguments. You need to do the lookup in the context yourself.