frctl / fractal

A tool to help you build and document website component libraries and design systems.
https://fractal.build
MIT License
2.1k stars 167 forks source link

Feature: @partial-block for nunjucks engine #1105

Open thommyhh opened 2 years ago

thommyhh commented 2 years ago

What problem would this feature solve?

The handlebars engine supports partial-blocks, making it possible to create wrapper components or override a component's content from parent/including template. I could not find a way to achieve the same result when using nunjucks as template engine.

What the feature should look like?

A nice way would be a partial tag, that renders the content between {% partial '@container-partial' %} and {% endpartial %} and make the result usable as variable or function in the container-partial. This would be similar to nunjucks {% call 'someMacro' %}...{% endcall %} tag using {{ caller() }} inside the macro to render/output the tag body.

I'm not familiar with the internals of either fractal or nunjucks, so I'm not able to create that myself. Therefore I hope, someone has the knowledge and the time to do that.

mihkeleidast commented 2 years ago

You should be able to use a regular variable in your component for the partial/block content. Then, in the parent component, use the set tag to create a variable block, then pass it into the child.

https://mozilla.github.io/nunjucks/templating.html#set

mihkeleidast commented 2 years ago

Otherwise, this seems like a wish for a twig-like embed tag: https://github.com/mozilla/nunjucks/issues/790

That issue has been open for five years with no solution. Even Mark, Fractal's creator, supported that addition. I would recommend for this to be requested upstream, as it's not really a Fractal-specific feature.

thommyhh commented 2 years ago

@mihkeleidast Thank you for your feedback. I will try the {% set ... %} workaround, even though it sounds a bit hacky.

My idea was, that the tag should resolve a component, so I thought it would be fractal specific. But the embed would be really nice. I'll take a look at that.

mihkeleidast commented 2 years ago

I think it would get the same template path resolving logic that the primary include et al tags use, so should not need anything specific for Fractal!

thommyhh commented 2 years ago

@mihkeleidast Ok, thanks.

I tried the ´{% set ... %}` approach, but this does not seem to work. My template looks like

{% set fieldsetContent %}
    foo
   {% render '@atoms-form-field', {id: 'name', label: 'Name'}, merge=True %}
{% endset %}
{{ fieldsetContent | dump() }}
{% render '@atoms-form-fieldset', {legend: null, fieldsetContent: fieldsetContent} %}

The result is

"\n foo\n "
<fieldset class="form__fieldset">
    <legend class="form__legend"></legend>

    foo

</fieldset>

It looks like, that the set does not wait for the render to finish. Any ideas?