How can I convert this TPL or PHP condition to a valid condition? - twig

I would like to add a condition to my twig file, but I can only find code examples for TPL or PHP. All my attempts to translate this into twig syntax have so far been unsuccessful. This may also be due to the fact that these examples are no longer up-to-date. Unfortunately, there is little current information about the open source vanilla forum. But as long as I don't even know if my twig syntax should actually work, I can't say that.
Can someone please help me and tell me if my twig syntax is correct?
Thank you for help!
This is what the relevant part of my twig looks like (I only want to display the main panel for Signed In users):
<div class="Frame-details">
{% if not isHomepage %}
<div class="Frame-row">
<nav class="BreadcrumbsBox" aria-label={{ t("Breadcrumb") }}>
{{ renderBreadcrumbs() }}
</nav>
</div>
{% endif %}
<div class="Frame-row">
<!-- Main Content -->
<section class="Content MainContent">
{{ renderControllerAsset("Content") }}
</section>
<!-- Main Content END -->
<!-- Main Panel -->
{% if UserSignedIn %}
<div class="Panel Panel-main">
{{ renderControllerAsset("Panel") }}
</div>
{% endif %}
<!-- Main Panel END -->
Here are the examples I've found so far:
For TPL is the following example:
{if $User.SignedIn}
Do some coding like show the Panel Asset
{/if}
For PHP is the following example:
$Session = Gdn::Session();
if ($Session->IsValid())
{
Show the Panel Asset
} else
{
Show only the Guest Box asset

Related

What would cause the same Django template include block to behave differently twice on the same page?

I'm trying to include a simple pagination template into a template that lists blog posts, but it gets output without getting interpreted, as in, I see the double curly brace enclosed tag as text in the resultant webpage (see image below).
Strangely, when I also paste same block higher in the page, and it gets interpreted fine. The same include, twice on the same page, different behavior!
Between the two, I iterate over the same object that gets passed to the pagination template, so this is probably something that I don't understand about the state of that object? Or Django's rendering process.
{% extends "blog/base.html" %}
{% block title %}My blog site thing{% endblock %}
{% block content %}
<h1>Blog site</h1>
{% include 'pagination.html' with page_object=posts %}
{% for post in posts %}
<h2>{{ post.title }}</h2>
<p class="date">Published {{post.publish}} by {{post.author}}</p>
{{post.body|truncatewords:5|linebreaks}}
{% endfor %}
{% include 'pagination.html' with page_object=posts %}
{% endblock %}
Pagination.html
<div class="pagination">
<span class="step-links">
{% if page_object.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page_object.number }} of {{ page_object.paginator.num_pages }}.
</span>
{% if page_object.has_next %}
Next
{% endif %}
</span>
</div>
views.py for this app
from django.shortcuts import render, get_object_or_404
from .models import Post
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def post_list(request):
object_list = Post.published.all()
paginator = Paginator(object_list, 3)
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
return render(request, 'blog/post/list.html', {'posts':posts})
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post, status='published',publish__year=year,publish__month=month, publish__day=day)
return render(request, 'blog/post/detail.html', {'post':post})
Here's what the resultant page looks like:
Here's the resultant html (I've added an extra line around the offending output to call it out)
<!DOCTYPE html>
<html>
<head>
<title>My blog site thing</title>
<link href="/static/css/blog.css" rel="stylesheet">
</head>
</html>
<body>
<div id="content">
<h1>Blog site</h1>
<div class="pagination">
<span class="step-links">
<span class="current">
Page 1 of 2.
</span>
Next
</span>
</div>
<h2>Another glorious post</h2>
<p class="date">Published March 2, 2022, 9:26 p.m. by admin</p>
<p>Lorem ipsum text Lorem ipsum …</p>
<h2>Classy post</h2>
<p class="date">Published March 2, 2022, 9:25 p.m. by admin</p>
<p>This is the way</p>
<h2>Another post</h2>
<p class="date">Published March 1, 2022, 7:26 a.m. by admin</p>
<p>Xyz</p>
{% include 'pagination.html' with page_object=posts %}
</div>
<div id="sidebar">
<h2>My blog</h2>
<p>This is my blog.</p>
</div>
</body>
I've even gone back and copy-pasted the actual code from the book I'm following (Django 3 by example, by Antonio Mele) and it's identical!
To any kind soul who has read this far, what am I missing?
Ok, so I just understood what was going on, and sharing in case it's useful to anyone else.
My IDE was mangling the formatting of the template file on save.
So the first include was a perfect little
{% include 'pagination.html' with page=posts %}
The second one ended up looking like
{% include
'pagination.html' with page=posts %}
When I turned off the auto-formatting and fixed the whitespace, it rendered fine.
So my big learning – probably obvious to many – is that whitespace matters in django template tags!.

Shopify Liquid: Paginating blog post based on tag

I'm going to try my best to explain this, sorry if it seems confusing.
I have a customized theme. I'm trying to take articles from the blog and put them into 7 separate tagged pages. Essentially to create separate blog templates standard one blog template. The pages bring in a section that paginates by 6.
I'm able to bring the blog articles into the section and paginate, but I'm unable to filter out the unnecessary tags. When I use if/unless statements inside the pagination loop, it just didn't render the unnecessary ones but still paginated based on it, so I had 3 articles on the first page, 2 on the second, and so on. Which make sense why it would do that.
I've tried the 'where' filter on my assign tag and the paginate tag, didn't work. When I asked on the Shopify Slack someone mentioned using the Section Render API with the endpoint '/blogs/{blog_id}/tagged/{tag_id}' but the returns all of the HTML from that page and I don't know how I'd parse and paginate over that. The Section Render API documentation is wanting, to say the least. And my experience with APIs is limited
The closest I've come to answer an is this answer: https://stackoverflow.com/a/60000460/12948634
The problem with the liquid solution is that I can apply a "view" to the tagged posts page but I still have to paginate over it. I still have to use the {% paginate blog.articles %} that apparently doesn't filter. Pagination isn't included in this theme and I'm not quite sure how to add that that to my 'blog-content.liquid' file without disturbing the main tagged page.
Any ideas? Code below:
<div id="article-index-card-section" class="g-flex">
{% assign blog = blogs.{blog_id} %}
{% paginate blog.articles by 6 %}
{% for article in blog.articles %}
<div class="article-index-card g-vertical">
<div style="display: flex; flex-direction: column;">
<img class="article-index-card-image" src="{{ article.image.src | img_url: 'master' }}">
<div class="article-index-card-text">
<h4>{{ article.title }}</h4>
<p class="t-body">{{ article.excerpt }}</p>
</div>
</div>
<div class="article-index-card-btn btn">
Learn More
</div>
</div>
{% endfor %}
<div>
{{ paginate | default_pagination: next: '>', previous: '<' }}
</div>
{% endpaginate %}
</div>
I will probably go the JS route in this case.
Here is what will I probably do, I don't know if it will fit your needs.
Create a separate blog.ajax.liquid template
We will create a new blog template and we will keep only the HTML need for the page to make the request faster and strip unused HTML elements.
{% layout none %}
<div id="article-index-card-section" class="g-flex">
{% paginate blog.articles by 6 %}
{% for article in blog.articles %}
<div class="article-index-card g-vertical">
<div style="display: flex; flex-direction: column;">
<img class="article-index-card-image" src="{{ article.image.src | img_url: 'master' }}">
<div class="article-index-card-text">
<h4>{{ article.title }}</h4>
<p class="t-body">{{ article.excerpt }}</p>
</div>
</div>
<div class="article-index-card-btn btn">
Learn More
</div>
</div>
{% endfor %}
<div>
{{ paginate | default_pagination: next: '>', previous: '<' }}
</div>
{% endpaginate %}
</div>
That's why we add the line {% layout none %} at the top to remove all of the HTML output from the default layout and only output the HTML on the template we create.
Make fetch request to that new template
We make a fetch request to the blog but we must specify that it must used the newly created template and not the default one.
fetch('/blogs/{blog_handle}/tagged/{tag}?view=ajax').then(res => res.text()).then(res => {
document.querySelector('.blog-holder').innerHTML = res;
})
For that we add the ?view=ajax to the end of the request, where the ajax part is the name of the template we created after blog.ajax.liquid.
This request needs to be done for each separate blog, so if you have 10 blogs you will do this request 10 times for each one.
Pagination request
The pagination request will be similar to the request of the blog but you will need to add the page=2 argument to the request where the 2 is the page number.
So something like so:
fetch('/blogs/{blog_id}/tagged/{tag_id}?view=ajax&page=2').then(res => res.text()).then(res => {
document.querySelector('.blog-template').innerHTML = res;
})
Blog main page
I will probably create a static section, where you will be able to select which blog goes on this page.
{%- for block in section.blocks -%}
{%- assign _block = block.settings -%}
{%- assign block_blog = _block.blog -%}
<div class="blog-template" data-handle="{{block_blog}}">
</div><!-- /.blog-template -->
{%- endfor -%}
<script>
document.querySelectorAll('.blog-template').forEach(item => {
const handle = item.getAttribute('data-handle');
// make fetch request and the logic for your tags
})
</script>
{% schema %}
{
"name": "Blogs",
"blocks": [
{
"type": "blog",
"name": "Blog",
"settings": [
{
"type": "blog",
"id": "blog",
"label": "Choose a blog"
}
]
}
]
}
{% endschema %}
This will be my personal choice of direction I go, I don't know if it will fit your needs.

Unique page identifiers in Grav CMS

I'm using the Grav CMS to create a modular web page; however, I'm having difficulty customizing the layout based on how the content is generated.
I've followed the documentation found Grav main site from which I've model my site after.
My folder structure is essentially:
pages
01.home
_section1
_section2
In each section folder I have my .md file. And each section is considered a sub-page of 'home'.
I've created the template file, modular.html.twig, in which I have the following code:
{% extends 'partials/base.html.twig' %}
{% block content %}
{% for child in page.children() %}
{{ child.content() }}
{% endfor %}
{% endblock %}
This code iterates through sub-pages to load the content onto the home page. In my template I'm simply printing the result of the content using {{ content }}
What I end up with is a page with vertically stacked content and repeating html,
as such.
What I want to do is uniquely define each sub-page (section) so that I can manipulate the content differently in my html, as such.
I've thought about creating separate template files for each section, but much of my content is nested.
For instance I have something akin to:
<div class="row">
<div class="section-1">
<h1>{{ content }}</h1> <!--Needs to be unique-->
</div>
<div class="section-2">
<h1>{{ content }}</h1> <!--Needs to be unique-->
</div>
</div>
Is it possible to accomplish what I'm trying to do with this framework? If so, how might I go about it?
Thank you
I think there are many ways to do this. For me, I use page's header to set CSS class of each section.
My section's md files could look like this (for example mysection.md)
---
title: Section 1
section_class: section-1
---
This is the content of section 1.
Here is my modular.html.twig:
{% extends 'partials/base.html.twig' %}
{% block content %}
<div class="row">
{% for child in page.children() %}
<div class="{{ child.header.section_class }}">
{{ child.content() }}
</div>
{% endfor %}
</div>
{% endblock %}
In my mysection.html.twig I print the section's content
<h1>{{ page.content }}</h1>
I hope this helps.

Cancelling parent template if variable is null in Twig

I'm new to Twig and I'm trying to figure out how to achieve the following.
I have an object with a set of properties that I want to render with different Twig templates depending on which type of property it is (text, images, date, etc).
I want to render them as follows:
<div class="row">
<div class="title">Title of property</div>
<div class="propertycontent">
//Specific property content depending on property type
</div>
</div>
My problem is that I can't figure out to skip the complete output if the property is not defined. I want to be able to use parent templates to take care of the "wrapping" of the rendered property content. Is it possible to use parent templates that returns nothing if the property value is undefined? Is there another good solution that does not rely on include "begin"/"end" for wrapping each template?
Thanks in advance.
Solution: Call parent with value(might be null) and title
Parent (propery_wrapper.twig):
{% if value %}
<div class="row">
<div class="title">{{title}}</div>
<div class="propertyContent">
{% block content %}{% endblock %}
</div>
</div>
{% endif %}
child (for height property):
{% extends 'property_wrapper.twig' %}
{% block content %}
{{ value.value|number_format(2, ',') }} m
{% endblock %}

Jekyll paginate blog as subdirectory

I'm using Jekyll for a static site and I'm trying to generate the blog as a subdirectory/subfolder:
http://example.com/blog
In the directory structure before running jekyll, this is blog/index.html.
I tried adding pagination by adding "paginate: 5" to _config.yml, but the generated url's were of the form:
http://example.com/page2/
i.e. no "/blog". This is fixed by:
paginate_path: /blog/page/:num
in _config.yml.
But the resulting generated pages at:
http://example.com/blog/page/2/
don't use blog/index.html as their layout. They use the root index.html. What's the point in even having the paginate_path option, then?
How do I get my blog at example.com/blog, with pagination, using Jekyll?
Use the destination key in your _config.yml file to set the base path where you want the output to be published to. For example,
paginate: 5
destination: _site/blog
Note that assuming your site is setup to server its root (e.g. "http://example.com/") from "_site" jekyll won't produce and "index.html" page at that location. Everything that jekyll builds will be under the "blog" directory, but that sounds like what you are after.
I found a fix via this page Basically it involves a bit of a hack to figure out if you are on the nth page of the blog and then includes a file that pulls in you blog section.
Create a file in _includes/custom/ called pagination. In that have your pagination code
<!-- This loops through the paginated posts -->
{% for post in paginator.posts %}
<h1>{{ post.title }}</h1>
<p class="author">
<span class="date">{{ post.date }}</span>
</p>
<div class="content">
{{ post.content }}
</div>
{% endfor %}
<!-- Pagination links -->
<div class="pagination">
{% if paginator.previous_page %}
Previous
{% else %}
<span class="previous">Previous</span>
{% endif %}
<span class="page_number ">Page: {{ paginator.page }} of {{ paginator.total_pages }}</span>
{% if paginator.next_page %}
Next
{% else %}
<span class="next ">Next</span>
{% endif %}
</div>
Now in your _layout/index.html add
{% if paginator.page != 1 %}
{% include custom/pagination %}
{% else %}
The original content of index
{% endif %}

Resources