Xzya / django-web-components

A simple way to create reusable template components in Django.
MIT License
159 stars 4 forks source link

class attributes as context #13

Closed nerdoc closed 6 months ago

nerdoc commented 7 months ago

Hi. Thanks for this awesome library.

What do you think of easily adding class attributes to the component, those being available automatically in the template?

This could lead to very cool things like:

@component.register("link")
class Link(component.Component):
    tag = "a"
    template_name=".../link.html"

    def get_context_data(self, **kwargs) -> dict:
        context = super().get_context_data(**kwargs)
        context.update(
            {
                "url": url = self.attributes.pop("url")
                "htmx": url = self.attributes.pop("htmx", None)
            }
        )
        return context

@component.register("linkbutton")
class LinkButton(Link):
    tag = "button"
    template_name=".../link.html"
{# link.html #}
<{{tag}}
  {% if htmx %} hx-get="{{url}}"
  {% else %}
    {% if tag == "a" %} href={{ url }}{% endif %}
{% endif %}
>
{% render_slot slot.inner_block %}
</{{tag}}

In my code this leads to significant less duplication. But I have to write the tag into the get_context_data() and make a super() call for inheriting. Class attributes would be inherited automatically.

The only thing that speaks agains that is to keep class attributes for "reactive" values later... ?

Xzya commented 6 months ago

Hey,

You should already be able to do that without having to override the get_context_data() method inside the child component, you just have to add the tag to the context in the parent (Link), e.g.:

@component.register("link")
class Link(component.Component):
    tag = "a"

    def get_context_data(self, **kwargs) -> dict:
        context = super().get_context_data(**kwargs)
        context.update(
            {
                "url": self.attributes.pop("url"),
                "htmx": self.attributes.pop("htmx", None),
                "tag": self.tag,
            }
        )
        return context

@component.register("linkbutton")
class LinkButton(Link):
    tag = "button"
nerdoc commented 6 months ago

Hm. OMG, did I really miss that? That's simple Python 1x1. Sorry for the spam :man_facepalming: .