Search code examples
checkboxbootstrap-4django-crispy-formsmodelform

How to customise the way a CheckboxSelectMultiple widget renders via crispyforms?


I have a Django ModelForm that renders a ForeignKey field using the CheckboxSelectMultiple widget. I want to be able to change the display of the checkboxes by adding and/or removing some css classes.

In the template, the form renders as follows:

<div id="id_activities" class="form-group">
    <label class="" for"">Choose Activities:</label>
    <div class="">
        <div class="custom-control custom-checkbox">
            <input id="id_activities_1" class="custom-control-input" type="checkbox" name="activities" value="1"/>
            <label class="custom-control-label" for="id_activities_1">..</label>
        </div>
    </div>
</div>

I would like to be able to customise the look of the checkboxes with some non-bootstrap classes. I've tried providing a template with the following html:

{% load crispy_forms_field %}

<div class="form-group">
    <label class="" for="">Choose Activities</label>
    <div>
        <div class="custom-control custom-checkbox addon">
            {% crispy_field field 'class' 'custom-control-input' %}
             <label class="custom-control-label small" for="{{ field.id_for_label }}">{{ field.label }}</label>
        </div>
    </div>
</div>

But that causes the input to be wrapped in a <ul> I am currently trying to override the bootstrap classes in my own scss file but feel dissatisfied with this workaround as I would like a bit more control. Is there an better way of customising the CheckboxSelectMultiple? Would I need to go as far as creating a custom Layout object?


Solution

  • To solve this I subclassed the CheckboxSelectMultiple widget and provided my own templates for tempate_name and option_template_name. I largely reused the django template code but exchanged the list elements for divs