Search code examples
templatesgulpfrontendnunjucksgulp-nunjucks-render

How to set macro variable in the page template for Nunjucks


I am using Nunjucks to set up a complicated site. My folder structure is as such:

frontend/
   |- dev/
   |- gulpfile.js
     |- css/
     |- images/
     |- js/
     |- pages/
       |- dashboard.njk
     |- templates/
       |- macros/
         |- header-macro.njk
       |- partials/
         |- _header.njk
         |- three-col.njk

I am attempting to have a macro (header-macro.njk) that causes the active class to be set on the nav link for the current page. It looks like this:

   {% macro active(activePage='dashboard') %}

    <nav class="header__nav">
        <a class="{% if activePage == 'dashboard' %}active{% endif %}" href="#">Dashboard</a>
        <a class="{% if activePage == 'locations' %}active{% endif %}" href="#">Locations</a>
        <a class="{% if activePage == 'reports' %}active{% endif %}" href="#">Reports</a>
        <a class="{% if activePage == 'services' %}active{% endif %}" href="#">Services &#38; Billing</a>
        <a class="{% if activePage == 'people' %}active{% endif %}" href="#">People</a>
    </nav>
{% endmacro %}

This would be imported into my _header.njk partial like so..

<div class="header__inner">
        <div class="header__logo"><img src="/images/logos/STN-y-15x100.png"></div>
            {% import 'macros/header-macro.njk' as nav %}

I want to set the nav.active variable in each page template. So in this case, that would be dashboard.njk

{% set page_title = "Welcome to eServices - Dashboard" %}
{% set body_class = "dashboard" %}
{{nav.active('dashboard')}}

But i get an error:

Error: Unable to call nav["active"], which is undefined or falsey

However, if i set nav.active('dashboard') in the _header.njk, everything works.

Am i missing something with the syntax or the folder structure?


Solution

  • The nav is defined in _header.njk scope. This scope is not available in dashboard.njk therefore you have nav as undefined. However you can use nav in _header.njk.

    // app.js
    var nunjucks  = require('nunjucks');
    var env = nunjucks.configure();
    
    var res = nunjucks.render('dashboard.njk');
    console.log(res); 
    
    // dashboard.njk
    DASHBOARD
    {% set activePage = 'dashboard' %} // Also you can pass it as a render prop.
    {% include "header.njk" %}
    
    // header.njk
    HEADER
    {% import 'macro.njk' as nav %}
    {{ nav.active (activePage) }} // pass activePage to macro-scope
    
    // macro.njk
    {% macro nav (activePage) %}
    <nav class="header__nav">
        <a class="{{ 'active' if activePage == 'dashboard' }}" href="#">Dashboard</a>
        ...        
    </nav>
    {% endmacro %}