Rendering a component inside another in Nunjucks & Fractal

574 views Asked by At

I'm working on a design system and just getting my head around the component way of thinking.

We're using Nunjucks and Fractal.

We have an existing component, an accordion which gets it's data from a JSON object. The props being title and content.

I've built a component, like a table of contents, which displays a list of styled links, using a simple loop, pulling in from a ToC.config.js file.

I need to include that new component within the accordion component, the ToC has a title and an array containing urls and text for each link.

At present I've just copied the HTML from the accordion's view in Fractal, but that's probably not the way to go, but visually it's as the designer requires.

I can also render the accordion correctly if I put all the links, HTML and all in the config, as a string, but that's not the way it should work either.

What I want to do, which is probably the proper way, is pull that accordion in and populate it with my ToC component.

{% render '@my-accordion', 'accordion: items' %} doesn't do what I want and I can't seem to figure out how to achieve what I need to do.

Something like so:

{% render '@my-accordion' %}
  // Pass in data from ToC, somehow
  {{ title: title }}
  {% for item in items %}
    {{ item.text etc }}
  {% endfor %} 

Then I would have my accordion component, where its title, links and HTML etc are those from my ToC component. Sorry for the rough pseudo above, it's more an example of what I want to do. I can't copy code to an external resource.

using render doesn't appear to be the way to go, unless I'm missing something? I can't pass the list through as a string as it has classes and aria for the current page etc and content authors will be building pages with these.

A little nudge in the right direction would be great.

1

There are 1 answers

0
Aikon Mogwai On

You can add a render-filter that similar to include and macro.

import 'nunjucks.min.js';

var env = new nunjucks.Environment({autoescape: true});

env.addFilter('render', function (template, ctx) {
    const html = env.render(template, ctx); // try-catch
    return env.filters.safe(html);
});

Usage

// table.njk
<table>
{% for e in rows %}
    {% 'row.njk' | render({row: e}) %}
{% endfor %}
</table>

// row.njk
<tr>
    {% for c in row.cols %}
        <td> {{ c.name }} </td>
    {% endfor %}
</tr>