Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add {% call ... %}{% endcall %} and caller() inside macros #930

Closed
wants to merge 4 commits into from

Conversation

PizzasBear
Copy link
Contributor

When a {% call ... %} block either has parameters right after call, or when the call block ends with the keyword with, the call is going to create a caller macro and expect an {% endcall %} block.

For example:

{% macro m(class) %}
    <div class="{{ class }}">
        {% call caller("<div>") %}
    </div>
{% endmacro %}
{% call(el) m("box") with %}
    I'm inside {{ el }}.
{% endcall %}

@djc
Copy link
Collaborator

djc commented Dec 8, 2023

For feature enhancements, please provide a clear use case of what you're trying to do and why it's hard without this feature.

@PizzasBear
Copy link
Contributor Author

I have a component that can filter elements inside it, and I'd like to call it with different contents:

{% macro filter_component(elements) %}
    <ol
        x-data="{
            elOrders: new Map(),
            fuse: new Fuse([]),
            createFuse() {
                fuse = new Fuse(
                    Array.from($el.children, el => ({ el, key: keyOf(el) })),
                    { keys: ['key'] },
                );
            },
            keyOf(el) { return el.dataset.key; },
            value: value,
        }"
        x-init="createFuse"
        @htmx:after-swap="createFuse"
        x-effect="elOrders = new Map(fuse.search(value).map((res, i) => [res.item.el, i + 1]))"
        style="display: flex;
               flex-direction: column;"
    >
        {% for el in elements %}
            <li
                data-key="{{ el.name }}"
                x-show="elOrders.get($el) !== undefined"
                :style="{ order: elOrders.get($el) }"
            >{% call caller(el) %}</li>
        {% endfor %}
    </ol>
{% endmacro %}

<div x-data="{ value: '' }">
    <input x-model="value">
    {% call(el) filter_component(my_elements) with %}
        Info about {{ el.name }}
    {% endcall %}
</div>

@djc
Copy link
Collaborator

djc commented Dec 8, 2023

Yeah, I don't think this is a good feature to generalize like this. I suggest you find a way to nest templates instead.

@djc djc closed this Dec 8, 2023
@PizzasBear
Copy link
Contributor Author

PizzasBear commented Dec 8, 2023

Can you explain better why this feature isn't good, or what you'd like to change about it? I've tried to stick as close to Jinja's call as I could while disambiguating it from the normal call with the with at the end.

@djc
Copy link
Collaborator

djc commented Dec 8, 2023

I think there's too much complexity here, and I think the template code becomes too hard to understand. While matching Jinja features is some part of what goes into design considerations, there are other considerations as well. For example, that it's generally straightforward to envision what Rust code is generated for any given template code. I think this feature fails that test, and with Rust's type system and the other features that Askama already has I think there are better ways to address this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants