django-crispy-forms / crispy-bootstrap5

Bootstrap5 template pack for django-crispy-forms
MIT License
460 stars 76 forks source link

keep wrapper in hidden field #164

Open nerdoc opened 11 months ago

nerdoc commented 11 months ago

With the upcoming of HTML-over-the-wire like HTMX, Unpoly etc., we are facing new challenges.

I am constructing a generic form that has the possibility of updating itself dynamically, based on django-forms-dynamic - but with HTMX functionality included.

This basically works perfectly with Crispy, with one except: When a conditional field triggers the absence of another field, I must "remove" that field from view. When the field is removed from the form itself, it is not rendered at all, and I don't have a tag with an id as HTMX target any more. I'd like to modifie django-forms-dynamic so that it just "hides" the field. This only works only with django crispy, as crispy adds a functional wrapper to each field which automatically has a id=div_id_<field-name>.

But, and this is my problem, if crispy renders a "hidden field", it just renders the field without wrapper. https://github.com/django-crispy-forms/crispy-bootstrap5/blob/2737939d424da36ccca95fbf6e48c49f9bd4b7df/crispy_bootstrap5/templates/bootstrap5/field.html#L3-L5

This makes it impossible to use it as target and hide/show it dynamically.

So I have a suggestion, that may be considered impossible as it may break things, but would help crispy to be more consistent with hidden fields:

Would it be possible to also enclose the hidden field in a div that has the same id as the visible field? this would be like:

{% if field.is_hidden %}
    <{% if tag %}{{ tag }}{% else %}div{% endif %} 
        id="div_{{ field.auto_id }}" 
        class="{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}"
    >
        {{ field }}
    </{% if tag %}{{ tag }}{% else %}div{% endif %}>
{% else %}

I expanded it a bit for better readability. What do you think about that?

nerdoc commented 11 months ago

Another possibility would be a DynamicField wrapper for Crispy fields, that holds that possibility, like the equivalent does for form fields in django-forms-dynamic.