So far, we have built the basic Node.js app, configured Nunjucks, learned about template inheritance, and Nunjucks tags for basic operations like creating and modifying variables, conditional statements, and loops. This time, we will learn how to create macros to avoid code repetition.
Creating a macro
Macros in Nunjucks are like functions in a programming language. To create one, you need the macro tag, which has the name of the macro and its parameters if required, and the closing tag endmacro. The logic goes between the two tags. Here is an example of a simple macro that provides a greeting text depending on the day of the week.
{% macro greeting(weekDay) %}
{% if weekDay === "Friday" %}
<span>It's almost the weekend.</span>
{% elif weekDay === "Saturday" or weekDay === "Sunday" %}
<span>Enjoy your weekend break.</span>
{% else %}
<span>It's just another working day.</span>
{% endif %}
{% endmacro%}
The parameters to the macro can have default values to use if the values are not provided in the macro call (for more details, see the documentation). An example of that in the following macro is the value for the target attribute of the html anchor tag.
{% macro link(url, text, targetValue = "_blank", routeParams=null, queryParamss=null) %}
{% if routeParams %}
{% for key, value in routeParams %}
{% set url = url | replace(":" + key, value) %}
{% endfor %}
{% endif %}
{% if queryParams %}
{% for key, value in queryParams %}
{% set operator = "?" if loop.first else "&" %}
{% set url = url + operator + key + "=" + value | replace(" ", "+") %}
{% endfor %}
{% endif %}
<a href="{{ url }}" target="{{ targetValue }}" rel="noopener noreferrer">{{ text }}</a>
{% endmacro %}
At this point in the tutorial, you should be able to understand the above code, though some parts require explanation. First is the following line:
{% set url = url | replace(":" + key, value) %}
It uses a replace filter. Filters, as explained in the Nunjucks documentation, are functions that can be applied to variables, are called with a pipe operator, and can take arguments. In this case, it replaces the route parameters with the provided values.
Another line that requires some explanation is
{% set operator = "?" if loop.first else "&" %}
It uses one of the few special variables that are provided with the for loop: loop.first, which is a boolean indicating the first iteration.
Using a macro
To use a macro, you have to import it into a template.
{% from "macros/greeting.njk" import greeting %}
Then you can use it for variable assignment
{% set greetingText = greeting(weekDay) %}
or directly in a block of code.
{% block mainContent %}
<p>Today is {{ weekDay }}. {{ greeting(weekDay) }}</p>
{% endblock %}
Happy coding!
