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

Form attributes duplicated in 'controls' div tag when using RadioSelect or CheckboxSelectMultiple widgets #1345

Open
glenvaughan opened this issue Mar 31, 2023 · 5 comments

Comments

@glenvaughan
Copy link

glenvaughan commented Mar 31, 2023

  • Package version: 1.13.0
  • Django version: 3.2
  • Python version: 3.9

Description:

When using either the RadioSelect or CheckboxSelectMultiple widgets for a ChoiceField, any attributes that are applied to the form through helper.attrs are being duplicated in the 'controls' div for that field when rendering the form with {% crispy form %}

Code:

forms.py

class CrispyTestForm(forms.Form):
    CHOICES = [(1, 'Foo'), (2, 'Bar')]

    foobar = forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect())

    def __init__(self):
        super().__init__()

        self.helper = FormHelper()
        self.helper.attrs = {
            'data-test': 'whatever',
        }

views.py

def crispy_test_view(request):
    context = {'form': CrispyTestForm()}
    return render(request, '/crispy_test.html', context)

crispy_test.html

{% load crispy_forms_tags %}

{% crispy form %}

Generated HTML

<form data-test="whatever" method="post"> <!-- ATTRIBUTE HERE AS EXPECTED -->

   <input type="hidden" name="csrfmiddlewaretoken" value="###########################"> 

   <div id="div_id_foobar" class="control-group">

      <label for="id_foobar_0" class="control-label requiredField">
         Foobar<span class="asteriskField">*</span> 
      </label>

      <div class="controls" data-test="whatever"> <!-- ATTRIBUTE REPEATED HERE -->

         <label for="id_foobar_0" class="radio"> 
            <input type="radio" name="foobar" id="id_foobar_0" value="1">
            Foo
         </label> 

         <label for="id_foobar_1" class="radio"> 
            <input type="radio" name="foobar" id="id_foobar_1" value="2">
            Bar
         </label> 

      </div>
   </div>
</form>

Same thing happens when using CheckboxSelectMultiple as the widget. I have not personally witnessed this behavior on any other widgets.

@smithdc1
Copy link
Member

smithdc1 commented Apr 1, 2023

hmmm yes. I think I'd tend to agree. But it's been like this ~forever (nearly 10 years at this point). It was introduced in

0097308#diff-8e3221922a193d1bb987407114a65f60b0e5a4212cead18a06c00048c2b4872f

Some LayoutObjects have their own flat_attrs, but that's not the case here.

self.flat_attrs = flatatt(kwargs)

I'd be tempted to drop the flat_attrs from those templates, but nervous about introducing a breaking change.

@glenvaughan
Copy link
Author

Is there any way that you know of to override the behavior from the form class?

My real-world use case is a form that updates a portion of the page through HTMX as soon as the form is changed, so having those hx-get etc attributes duplicated on a particular form field wreaks havoc. Minor variations of this form are used in many places, so manually laying out the form HTML in the templates is not a route I want to go.

At present, the "workaround" I'm using is to just stick with the default Select and SelectMultiple fields, but in many cases the RadioSelect and CheckboxSelectMultiple widgets would be strongly preferred.

@smithdc1
Copy link
Member

Is there any way that you know of to override the behavior from the form class?

I don't think so. The best I could suggest is to set form_tag=False on the form helper, and then add it to your template. [1]

I think we should look at correcting the template. Which template pack are you using? If folk want to target that <div> with an additional class they can use field_class instead. [2]

[1] https://django-crispy-forms.readthedocs.io/en/latest/form_helper.html

[2] https://github.com/django-crispy-forms/crispy-bootstrap4/blob/5397030e97019d818d2e697f9dce1a667979eb34/crispy_bootstrap4/templates/bootstrap4/layout/checkboxselectmultiple.html#L4

@esseti
Copy link

esseti commented Oct 9, 2023

@glenvaughan did you find a workaround? i've lost 3 hours trying to get why my htmx did not work properly. it's due to that extra div thing.
I was wondering of creating my ad-hoc layout html for the two widgets by removing the div flat_attrs.

@esseti
Copy link

esseti commented Oct 9, 2023

Wait, the problem seems to be fixed here: https://github.com/django-crispy-forms/crispy-bootstrap4/blame/main/crispy_bootstrap4/templates/bootstrap4/layout/radioselect.html#L4 but the release of that is missing apparently.

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

No branches or pull requests

3 participants