Search code examples
javascriptnpmgulptemplate-enginenunjucks

Templating solution for nested variables using nunjucks or other method


I have just started using gulp & nunjucks for templating (emails in this case).

I want to solve the problem of calling a module/partial and assigning different values to the attributes each time that it is processed.

It initially seems like a job for a for loop but the module will not necessarily be called upon in sequence within the template

Within the module there are attributes which are assigned to variables. I would like to resolve those variables differently depending on the section that the module is being used for.

A very basic example would be - in an index file I'd have :

{% block content %}


<!-- logo start -->

{% include genericMod %}

<!-- logo end -->


<!-- some other section start -->

{% include someOtherMod %}

<!-- some other section end -->


<!-- hero start -->

{% include genericMod %}

<!-- hero end -->


{% endblock %}

And in the genericMod itself-:

<tr>

 <td class="full-width-image" align="{{align}}" ><img src="{{src}}" alt="{{alt}}"/></td>

</tr>

The kind of functionality I'd like to tap into would be to define a “modKey” i.e. a variable within each variable in the module e.g.

{{modKey.align}}

{{modKey.src}}

{{modKey.alt}}

Then be able to somehow assign that key to the module each time it is called:

<!-- logo start —>

{% include genericMod "modKey": "logo" %}

<!-- logo end -->

So the above produces:

<tr>

 <td class="full-width-image" align="{{logo.align}}" ><img src="{{logo.src}}" alt="{{logo.alt}}"/></td>

</tr>

And:

<!-- hero start -->

{% include genericMod "modKey": "hero" %}

<!-- hero end -->

produces:

<tr>

 <td class="full-width-image" align="{{hero.align}}" ><img src="{{hero.src}}" alt="{{hero.alt}}"/></td>

</tr>

So that when piped through a json file the respective data would be rendered for each attribute variable:

"logo": {
    "alt": "some logo alt text",
    "href": "http://www.someurl.com",
    "align": "left"
  },
 "hero": {
    "alt": "some hero alt text",
    "href": "http://www.someotherurl.com",
    "align": "centre"
  }

Obviously that's just a hypothetical solution but is there a way of actually achieving something similar?


Solution

  • It turns out the solution is very simple. I had been assigning the value of the context var to a string rather than a variable name when trying to use 'set'.

    For the record this works...

    {% set data = logo %} 
    {% include oneIncludeFile %} 
    {% set data = hero %} 
    {% include otherIncludeFile %}
    

    where the include file would be referencing e.g. {{ data.alt }} or {{ data.href }}.

    Though a macro might be a better means to achieve this:

    {% macro foo(data) %} 
    <a href="{{ data.href }}"><img src="{{ data.src }}" alt="{{ data.alt }}" /></a> 
    {% endmacro %}
    

    and then call it like {{ foo(logo) }} and {{ foo(hero) }} to pass in different sets of data.

    Full explanation can be found here: https://github.com/mozilla/nunjucks/issues/779