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

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

Open
dfrankow opened this issue Jan 26, 2023 · 18 comments

Comments

@dfrankow
Copy link

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.

@dfrankow
Copy link
Author

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.

@dfrankow
Copy link
Author

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

@dfrankow
Copy link
Author

dfrankow commented Jan 26, 2023

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>

@dfrankow
Copy link
Author

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).

@mordechaiyosef
Copy link

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.

@dfrankow
Copy link
Author

dfrankow commented Mar 4, 2023

@mordechaiyosef Thanks for letting me know!

@foggy54
Copy link

foggy54 commented Mar 5, 2023

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

@dfrankow
Copy link
Author

dfrankow commented Mar 5, 2023

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.

@Actionb
Copy link

Actionb commented Mar 8, 2023

@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/[email protected]/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'})

@mordechaiyosef
Copy link

mordechaiyosef commented Mar 9, 2023

@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/[email protected]/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

@Actionb
Copy link

Actionb commented Mar 10, 2023

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/[email protected]/dist/select2-bootstrap-5-theme.css" />
    <!-- bootstrap -->
    {% bootstrap_css %}
    {% bootstrap_javascript %}
    ...
</head>
<body>
<form>
    {% bootstrap_form form layout="horizontal" %}
</form>
</body>

@mordechaiyosef
Copy link

mordechaiyosef commented Mar 10, 2023

@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 %}

@Actionb
Copy link

Actionb commented Mar 10, 2023

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%;"})

@mordechaiyosef
Copy link

@Actionb it works! thanks a bunch :)

@mister727
Copy link

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

@MaxiG-ai
Copy link

MaxiG-ai commented Jun 4, 2024

Thanks a lot @mordechaiyosef @Actionb @dfrankow , this helped me a ton!

@antoineprobst
Copy link

antoineprobst commented Jul 15, 2024

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>

Thank you for your solution it helped me !

I also had to add :

.select2-container .select2-selection--single{
    height: 42px;
}

to make it look good. (and at the bottom of the page after the media files for form is loaded)

@gamesbook
Copy link

gamesbook commented Jul 15, 2024

Are all these changes backwards-compatible or for v5 only?

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

8 participants