Reputation: 1812
In my layout.html (sometimes called base.html) I have a navbar like this:
<li class="dropdown"><a href="{% url 'index' %}" >Home </a></li>
<li class="dropdown"><a href="{% url 'house_list' %}">Your houses</a></li>
<li class="dropdown"><a href="{% url 'agency_list' %}">Agencies</a></li>
<li class="dropdown"><a href="/admin">Admin</a></li>
<li class="dropdown"><a href="{% url 'logout' %}"><i class="fa fa-lock"></i> Log ud</a></li>
<li class="dropdown"><a href="{% url 'login' %}"><i class="fa fa-lock"></i> Log ind</a></li>
I would like to highlight the current page in the navbar which is done by changing <li class="dropdown">
to <li class="dropdown active">
Is there a way for Django to insert active for the page the user is on? Any help is much appreciated!
I'm using Django 1.9 and Python 3.5.
Upvotes: 16
Views: 10389
Reputation: 639
I was running into the same issue with my code base(Django + bootstrap4). I didn't want to specify all the highlighted routes myself and wanted something which supports nested paths as well. The following solution uses vanilla JS with xpath selectors to search for all the nav-items and compare them with the document's location path.
let navItemsIter = document.evaluate('//li[@class="nav-item"]//a', document);
function getPathBase(path) {
let pathBase = path.split('/').filter(function(e){return e})
if(pathBase.length===0) return null;
return pathBase[0];
}
try {
const pathBase = getPathBase(document.location.pathname);
var navNode = navItemsIter.iterateNext;
while(navNode) {
navNode = navItemsIter.iterateNext();
if(pathBase===getPathBase(navNode.attributes.href.nodeValue)) {
navNode.attributes.class.nodeValue = navNode.attributes.class.nodeValue+' active'
break;
}
}
} catch(err) {
console.log('Error: Document tree modified during iteration', err)
}
You might need to change the xpath selector based on your html's structure.
Upvotes: 1
Reputation: 1026
I have a simple solution: In your views.py pass an additional parameter in your context dictionary
def home(request):
return render(request, 'template_name', {'home_page': 'active'})
then in your base.html (where you have the navbar):
<li class="nav-item {{home_page}}">
<a class="nav-link" href="{% url 'home' %}">Home</a>
</li>
In this way whenever you will pass call the home function it will also send the 'home_page' which will make the current URL acitve.
Note that I am using bootstrap here.
Upvotes: 3
Reputation: 1379
When not using a dedicated template tag
for the menu generation, I set the active
menu item class if the view_name
of the current request matches the view_name
of the linked item:
Pseudo code:
<a
class="{% if request.resolver_match.view_name == 'foo' %}active{% endif %}"
href="{% url 'foo' %}"
>Foo</a>
Not very DRY, but when not dealing with a lot of navigation items it does the job:
<a class="nav-item nav-link {% if request.resolver_match.view_name == 'core:dashboard' %}active{% endif %}" href="{% url 'core:dashboard' %}">Dashboard</a>
<a class="nav-item nav-link {% if request.resolver_match.view_name == 'publications:index' %}active{% endif %}" href="{% url 'publications:index' %}">Publications</a>
Upvotes: 4
Reputation: 3715
You can get the name of the url (referenced in your urlpatterns). Then set the 'active' class if the url matches.
{% with url_name=request.resolver_match.url_name %}
<li class="dropdown {% if url_name == 'index' %}active{% endif %}"
<a href="{% url 'index' %}" >Home </a>
</li>
<li>...</li>
{% endwith %}
Upvotes: 41
Reputation: 1630
You need to specify below script in your HTML file. Here we are retrieving current window anchor tag and then adding the active class to the respective <li>
tag.
$(document).ready(function(e){
var pathname = window.location.pathname;
atag = $('.dropdown a[href="'+pathname+'"]'); #Here you should mention your <li> class name "dropdown"
atag.parent().addClass("active");
});
Upvotes: 1
Reputation: 43
I had a simialr question and found that using Djangos templates solved my issue. By creating a 'base' template containing the navbar, leaving the active flag to be populated by each page.
Like this:
base.html file containing this
<li {% block nav_index%}{% endblock %}><a href="{% url 'index' %}" >Home </a></li>
<li {% block nav_house_list%}{% endblock %}><a href="{% url 'house_list' %}">Your houses</a></li>
<li {% block nav_agency_list%}{% endblock %}><a href="{% url 'agency_list' %}">Agencies</a></li>
<li {% block nav_admin%}{% endblock %}><a href="/admin">Admin</a></li>
<li {% block nav_logout%}{% endblock %}><a href="{% url 'logout' %}"><i class="fa fa-lock"></i> Log ud</a></li>
<li {% block nav_login%}{% endblock %}><a href="{% url 'login' %}"><i class="fa fa-lock"></i> Log ind</a></li>
Then referencing that on each page. Inserting 'active' for each url:
{% extends "base.html" %}
{% block nav_index%}
class="active"
{% endblock %}
(replace nav_index for each page)
Django has some good documentation on it: https://docs.djangoproject.com/en/1.7/topics/templates/
Upvotes: 4