Setting current category to active - timber

When on a category page I'm hoping to add an "active" class the current pages relevant link to show which category is selected in the menu.
Currently I'm listing all post categories and linking to their relevant pages via
{% for cat in categories %}
<li><a style="margin: 0;" href="{{ cat.link }}" class="">{{cat.name}}</a></li>
{% endfor %}
I have tried using if statements but can't seem to get it right.

Managed to solve this by setting the current category to active like this:
{% for cat in categories %}
<li><a style="margin: 0;" href="{{ cat.link }}" class="menu-item {% if category|capitalize == cat.name %}active{% endif %}">{{cat.name}}</a></li>
{% endfor %}

Related

How to get current page in pages Symfony 5 without duplicate code?

I want get the current page and give an active class without duplicate code in symfony 5.
Here is the code example :
<li class="{{ app.request.get('_route_')=='home' ? 'active':''}}">
Home
</li>
<li class="{{ app.request.get('_route_')=='contact' ? 'active':''}}">
Contact
</li>
</ul>
As an extension of the answer of #DhiaDjobbi
I've you really want to reduce "duplicate" code, I'd go with defining the menu in an array as well
{% set active_page = app.request.get('_route') %}
{% for page in pages %}
<li {% if page == active_page %} class="active" {% endif %} >
{{ page }}
</li>
{% endfor %}
U can create a twig variable in Template its better readable.
{% set page = app.request.get('_route') %}
Then use If Condition to test.
<li {% if page == 'home' %} class="active" {% endif %} >
Home
</li>
<li {% if page == 'contact' %} class="active" {% endif %} >
Contact
</li>

For loop in Timber Twig file returns three copies of same image (should be 3 different images)

I'm building my first Timber Wordpress theme and using the timber-starter-theme. I have a custom content type with custom fields (fields added using WCK plugin). I haven't touched single.php file, just building the twig template. 'team_church_slide' is a repeating field to add images to go into a Slick carousel. My template section is:
{% set slickSlider = post.team_church_slideshow %} {# the field group #}
{% set slickSlide = post.get_image('team_church_slide') %} {# the field #}
{% if slickSlider %}
<div class="slick-slider">
<ul>
{% for slides in slickSlider %}
<li><img src="{{ slickSlide.src }}" alt="{{ slickSlide.alt }}"></li>
{% endfor %}
</ul>
</div>
{% endif %}
This returns the image correctly, but three copies of the first image, not the three different images which are uploaded. If I remove an uploaded image, two copies of the first image are shown.
Is there something to change in the twig to get all the images?
Figured this out thanks to something in this post:
Get first row from ACF Repeater using Timber
Here's my final working template section:
{% set slickSlider = post.team_church_slideshow %}
{% if slickSlider %}
<div class="slick-slider">
<ul>
{% for slides in slickSlider %}
{% set slickSlide = TimberImage(slides.team_church_slide) %}
<li class="slide">
<img src="{{ slickSlide.src }}" alt="{{ slickSlide.alt }}">
</li>
{% endfor %}
</ul>
</div>
{% endif %}
The only real change was 'post.get_image' to 'TimberImage' & moving the set inside the for-loop.

How to interpolate a variable in a twig loop to render a file?

I am looping through a list of social profiles to render the logo. Each social item has a field of svg_icon_code that looks like "twitter" or "facebook". I want to use this code to render the correct file. Currently I am just hardcoding in "twitter" resulting in all logos being the Twitter svg. How can I use the icon_code to render the correct svg?
{% for item in options.social_media_links %}
<li class="header__social-media-links__item">
<a href="{{item.link}}" target="_blank">
{% include 'component/svg-twitter-icon.twig' %}
</a>
</li>
{% endfor %}
You need to concat the icon like this,
{% for item in options.social_media_links %}
<li class="header__social-media-links__item">
<a href="{{item.link}}" target="_blank">
{% include 'component/svg-'~item.svg_icon_code~'-icon.twig' %}
</a>
</li>
{% endfor %}
If an icon doesn't have a template or the template is missing you can do this to render a default icon
{% for item in options.social_media_links %}
<li class="header__social-media-links__item">
<a href="{{item.link}}" target="_blank">
{% include [ 'component/svg-'~item.svg_icon_code~'-icon.twig', 'component/svg-default-icon.twig' ] %}
</a>
</li>
{% endfor %}

Django CMS Multi-Level Dropdown Menu

Im kinda new to Django CMS and im trying my best to avoid asking, but this one drives me crazy.
I made a Wiki app with a Topic, and Category model. I hooked it to a Site on my CMS and added it to my Menu. Now i would like to be able to show all Top-Level categories, their Child Categories & Topics, and the Child categories of these, and so on, on my menu.
Menu/Navigation should look like this:
Wiki
Category1
Category1.1
Topic
Category1.2
Topic
Category2
Topic
Category3
...
Right now i can only show the Top categories:
Wiki
Category1
Category2
Category3
I Already created a menu.py to get a Custom SubMenu on my Wiki (the one you see above):
menu.py
class WikiSubMenu(CMSAttachMenu):
name = _("Wiki Sub-Menu")
def get_nodes(self, request):
nodes = []
categories = Category.objects.filter(parent_id__isnull=True)
for c in categories:
node = NavigationNode(
mark_safe(c.name),
c.get_absolute_url(),
c.id,
)
nodes.append(node)
return nodes
menu_pool.register_menu(WikiSubMenu)
My Category Model:
class Category(models.Model):
''' Category model. '''
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
parent = models.ForeignKey(
'self',
null=True,
blank=True,
related_name='children'
)
sort = models.IntegerField(default=0)
class Meta:
ordering = ['sort', 'name']
def __unicode__(self):
return self.name
#models.permalink
def get_absolute_url(self):
return ('topics:categories_category_detail', (), {'slug': self.slug})
def get_all_children(self):
return Category.objects.filter(parent=self)
Now, is it possible to create a Sub-SubMenu, for all Categories with Childs, and their Childs, and their Childs, and so on?
Thanks for help & sorry for bad english
-- EDIT : --
I just found that:
docs.django-cms.org/en/3.0.6/extending_cms/app_integration.html#integration-modifiers
(Removed direct link to add 2 new Links, sorry for that)
I think that is what im looking for, i was kinda blind that i didn't found it. I'll try it out and Post the Answer if it worked out.
-- EDIT (AGAIN): --
The modifier didn't worked for me, but i got a whole piece further,
i read the Docs again, and found that i can give the NavigationNodes an optional attr dictonary, which i filled with all Categories with parent=c, on that way i had the data i needed, then i found that real nice bootstrap dropdown menu, that does exacly what i wanted. So my code until now looks like that:
menu.py
class TopicsSubMenu(CMSAttachMenu):
name = _("Wiki Sub-Menu")
def get_nodes(self, request):
nodes = []
categories = Category.objects.filter(parent_id__isnull=True)
for c in categories:
node = NavigationNode(
mark_safe(c.name),
c.get_absolute_url(),
c.pk,
attr=dict(
subcategories=Category.objects.filter(parent=c),),
)
nodes.append(node)
return nodes
And my Template:
menu.html
{% for child in children %}
<li>
{% if child.children %}
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
{{ child.get_menu_title }}
<span class="caret">
</span>
</a>
<ul class="dropdown-menu multi-level" role="menu" aria-labelledby="dropdownMenu">
{% for child in child.children %}
{% if child.attr.subcategories.count %}
<li class="dropdown-submenu">
<a tabindex="-1" href="#">{{ child.get_menu_title }}</a>
<ul class="dropdown-menu">
{% for subcategory in child.attr.subcategories %}
<li>
<a tabindex="-1" href="{{ subcategory.get_absolute_url }}">{{ subcategory }}</a>
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li>{{ child.get_menu_title }}</li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<a href="{{ child.get_absolute_url }}">
<span>
{{ child.get_menu_title }}
</span>
</a>
{% endif %}
</li>
{% if class and forloop.last and not forloop.parentloop %}
{% endif %}
{% endfor %}
My next step will be to write the whole "for" loops from the template in a Method, make it recursive with a while loop or something and post the result as Answer.
I hope i can help someone with that stuff :)
WOHO! I finally did it!
base.html
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
{% show_menu 0 100 100 100 "menu.html" %}
</ul>
</div>
menu.html:
{% for child in children %}
<li class="child{% if child.selected %} selected{% endif %}{% if child.ancestor %} ancestor{% endif %}{% if child.sibling %} sibling{% endif %}{% if child.descendant %} descendant{% endif %}{% if child.children %} dropdown{% endif %}">
<a {% if child.children %}class="dropdown-toggle" data-toggle="dropdown"{% endif %} href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">
<span>{{ child.get_menu_title }}</span>{% if child.children|length %}<span class="caret"></span>{% endif %}
</a>
{% if child.children %}
<ul class="dropdown-menu multi-level" role="menu" aria-labelledby="dropdownMenu">
{% show_menu from_level to_level extra_inactive extra_active "dropdownmenu.html" "" "" child %}
</ul>
{% endif %}
</li>
{% if class and forloop.last and not forloop.parentloop %}{% endif %}
{% endfor %}
and my dropdownmenu.html:
(The recursive stuff starts here)
{% load i18n menu_tags cache mptt_tags %}
{% for child in children %}
<li {% if child.children %}class="dropdown-submenu"{% else %} {% endif %}>
<a tabindex="-1" href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title }}</a>
{% if child.children %}
<ul class="dropdown-menu">
{% show_menu from_level to_level extra_inactive extra_active "dropdownmenu.html" "" "" child %}
</ul>
{% endif %}
</li>
{% endfor %}
and the most important, menu.py:
class TopicsSubMenu(CMSAttachMenu):
name = _("Wiki Sub-Menu")
def get_nodes(self, request):
nodes = []
categories = Category.objects.all()
for c in categories:
node = NavigationNode(
mark_safe(c.name),
c.get_absolute_url(),
c.pk
)
if c.parent:
node.parent_id = c.parent_id
nodes.append(node)
topics = Topic.objects.all().exclude(category__isnull=True)
for t in topics:
node = NavigationNode(
mark_safe(t.title),
t.get_absolute_url(),
t.pk,
t.category.all()[0].id,
parent_namespace="TopicsSubMenu"
)
nodes.append(node)
return nodes
menu_pool.register_menu(TopicsSubMenu)
And thats it!

Is it possible to style posts in octopress according to its tags?

I need to style all the posts in Octopress which have the tag 'old' differently. Like, show only the title and no image in archives and keep them separated! How can I do this? (Note : There are nearly 1,500 posts with the old tag)
You could simply use the tags as css classes:
<ul>
{% for post in site.posts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
That way you can style the link easily via css for any tag.
I'll assume you have a old class that differentiates the posts or that you can style a list of old posts with a old_posts class. You can create two separate lists:
<ul class="old_posts">
{% for post in site.tags.old %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
<ul class="new_posts">
{% for post in site.posts %}
{% unless post.tags contains 'old' %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
Or you can create one list with the old posts receiving a special class old:
<ul>
{% for post in site.posts %}
{% if post.tags contains 'old' %}
<li>{{ post.title }}</li>
{% else %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
Basically, site.posts, post.tags and site.tags.TAGNAME, together with Liquid's if-else, for and contains are able to do most of the tasks related to styling specifically tagged posts.

Resources