yourlabs/django-autocomplete-light

single-select autocomplete does not look good using django-bootstrap5 bootstrap_form

dfrankow opened this issue ยท 18 comments

Below is a screenshot of a single-select and multi-select form rendered with {% bootstrap_form myform %}, a tag from django-bootstrap5.

Closed:

Screen Shot 2023-01-26 at 11 42 57 AM

Open:

Screen Shot 2023-01-26 at 11 43 36 AM

Unfortunately, I don't know a ton about bootstrap5 forms, so I don't know the exact styling it's missing, or how to customize it. I'd have to do more research.

For more details of form object, template, etc., see https://stackoverflow.com/questions/75249988/why-is-django-autocomplete-light-single-select-badly-styled-and-broken-when-mult.

It looks like adding padding-bottom: 36px to .select2-selection--single might be close to a fix.

Now I have to find how to do that custom styling.

Ah, but it still has two arrows. Not sure how to fix that?

If this helps anyone else, I added the hacks below to my CSS. Not sure if that is a good idea, but here we go.

<style>
.select2-selection--single {
    /* Existing options: */
    background-color: #fff;
    border: 1px solid #aaa;
    border-radius: 4px;
    /* HACK: new option to make padding right: */
    padding-bottom: 36px;
}

/* HACK: make default django-autocomplete-light arrow go away (so bootstrap shows): */
.select2-selection__arrow {
    visibility: hidden;
}
</style>

Also: I could not find how to style just that box, so I just dumped this CSS in the page globally.

Is there somewhere in the docs that talks about styling the widget? I saw I can pass select2 options (don't want that), and that I can style the results of the autocomplete view (don't want that).

hey @dfrankow,

thanks for the snippet. this helped me with the same issue. I hope there is an official less hacky solution in the future.

@mordechaiyosef Thanks for letting me know!

Hello @dfrankow , thank you very much, I also had the same issue and your "hack" helped a lot. BTW may be you can help with other similar issue, I'm trying to use autocomplete form with tag class = "form-control" and for some reason they have different width, comparing to just normal input forms, may be you have any suggestions how to fix that? I've tried to add attrs={'width':'500'} , but due to this form looses it's fluid size ability.
image

My only suggestion is to use the browser css explorer to see which styles are applied to each of those boxes, and turn on and off various attributes until it looks the way you want. That's what I did, just experimented.

@dfrankow You could use the bootstrap5 theme for select2.
https://apalfrey.github.io/select2-bootstrap-5-theme/

  1. include the theme css, f.ex. in your template: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.css" />.
  2. pass the theme to the widget using its attrs like so autocomplete.ModelSelect2(attrs={'data-theme': 'bootstrap-5'})

@dfrankow You could use the bootstrap5 theme for select2. https://apalfrey.github.io/select2-bootstrap-5-theme/

  1. include the theme css, f.ex. in your template: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.css" />.
  2. pass the theme to the widget using its attrs like so autocomplete.ModelSelect2(attrs={'data-theme': 'bootstrap-5'})

@Actionb this doesnt seem to fix the issue

Applying the theme should change the look. It certainly does for me.

bootstrap5_theme

class MyForm(forms.Form):
    single_select = forms.ChoiceField(
        label="Not themed",
        choices=[('foo', 'Foo'), ('bar', 'Bar'), ('spam', 'spam')],
        widget=autocomplete.Select2()
    )
    single_select_themed = forms.ChoiceField(
        label="Themed",
        choices=[('foo', 'Foo'), ('bar', 'Bar'), ('spam', 'spam')],
        widget=autocomplete.Select2(attrs={'data-theme': 'bootstrap-5'})
    )

Template:

<head>
    ...
    <!-- select2 bootstrap theme -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.css" />
    <!-- bootstrap -->
    {% bootstrap_css %}
    {% bootstrap_javascript %}
    ...
</head>
<body>
<form>
    {% bootstrap_form form layout="horizontal" %}
</form>
</body>

@Actionb I am seeing multiple fields with different field sizes

Screenshot_20230310_110422

form:

class EditEventForm(forms.ModelForm):
    single_select = forms.ChoiceField(
        label="Not themed",
        choices=[("foo", "Foo"), ("bar", "Bar"), ("spam", "spam")],
        widget=autocomplete.Select2(),
    )
    single_select_themed = forms.ChoiceField(
        label="Themed",
        choices=[("foo", "Foo"), ("bar", "Bar"), ("spam", "spam")],
        widget=autocomplete.Select2(attrs={"data-theme": "bootstrap-5"}),
    )

    event_slug = forms.ChoiceField(
        choices=get_holiday_tuples(),
        label="Event Name",
        widget=autocomplete.Select2(attrs={"data-theme": "bootstrap-5"}),
    )
    message_type = forms.ChoiceField(
        choices=MessageTypeChoices.choices,
        widget=autocomplete.Select2(attrs={"data-theme": "bootstrap-5"}),
        help_text="what type of message to send",
    )
    social_circles = forms.MultipleChoiceField(
        label="Event Name",
        choices=SocialCircleChoices.choices,
        required=False,
        widget=autocomplete.Select2Multiple(
            attrs={
                "data-placeholder": "choose all to send to everyone you know",
            },
        ),
        help_text="Combine social circles to easily organize who you want to send to.",
    )
    contacts = forms.ModelMultipleChoiceField(
        required=False,
        queryset=Contact.objects.all(),
        widget=ModelSelect2Multiple(
            url="contact_autocomplete",
            attrs={
                "data-placeholder": "Start Typing...",
            },
        ),
        help_text="Add specific contacts in addition to previous selected social circles.",
    )

    class Meta:
        model = SignificantEvent
        fields = [
            "single_select_themed",
            "event_slug",
            "message_type",
            "social_circles",
            "contacts",
        ]

template:

{% load django_bootstrap5 %}
{% bootstrap_messages %}
<div class="d-flex justify-content-center py-5">
    <div class="card shadow-sm">
        <div class="card-header text-center"><h3>{% if object.id %}Edit {{ verbose_name }}: {{object}} {% else%}Create {{ verbose_name }}{% endif %}</h3>
        </div>
        <div class="card-body">
            <form method="post">{% csrf_token %}
                {% bootstrap_form form layout="horizontal" %}
                <button class="btn btn-primary btn-block m-4" value="Update" type="submit">
                    Save
                </button>
            </form>
        </div>
    </div>
</div>
{% endblock %}

Oh you mean the width of the container? https://select2.org/appearance#container-width

Set it like so: widget=autocomplete.Select2(attrs={"data-theme": "bootstrap-5", "style": "width: 100%;"})

@Actionb it works! thanks a bunch :)

Thank you for the previous information which was very useful to me.
However, I searched a lot on google but I can't find a solution to change the form rendering of forms.
Indeed, how to obtain forms instead of lists ?

image

But not
image

Thanks a lot