zostera / django-bootstrap4

Bootstrap 4 integration with Django.
https://django-bootstrap4.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.03k stars 263 forks source link

bootstrap4 custom form widgets support #116

Open last-partizan opened 6 years ago

last-partizan commented 6 years ago

Hello, i'm using custom-radio and custom-checkbox in my project, and to support it i had to override FieldRenderer.

https://getbootstrap.com/docs/4.1/components/forms/#checkboxes

Now something changed and i need to adjust my code, maybe it's better to implement support for those widgets in project? If it would be useful, i could implement it and make pull-request.

sedrubal commented 5 years ago

I also want to use the custom control inputs as widgets. I especially like the Switch of bootstrap 4.2.

roelandxyz commented 5 years ago

Support for the custom file input would also be nice.

dyve commented 5 years ago

Yes, this would be very cool indeed. The Django way would be to use the default widget unless another widget is specified. If a form has a Widget that is recognizable as a Bootstrap4Widget, the FieldRenderer could delegate the HTML rendering to the widget?

last-partizan commented 5 years ago

@dyve Probably it can be done this way, but i don't see any widget-rendering delegation inside django-bootstrap4.

Right now in my project i'm using custom field renderer with this mixin:

class AwesomeRenderer:
    """
    Render checkboxes for custom wodgets
    https://getbootstrap.com/docs/4.1/components/forms/#checkboxes
    """
    CUSTOM_CONTROL_CLASS = {
        "radio radio-success": "custom-control custom-radio",
        "checkbox": "custom-control custom-checkbox",
    }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if isinstance(self.widget, forms.CheckboxInput):
            self.widget.attrs.update({"class": "custom-control-input"})

    def add_checkbox_label(self, html):
        return html + render_label(
            content=self.field.label,
            label_for=self.field.id_for_label,
            label_title=escape(strip_tags(self.field_help)),
            label_class="custom-control-label",
        )

    def wrap_widget(self, html):
        if isinstance(self.widget, forms.CheckboxInput):
            html = '<div class="custom-control custom-checkbox">{content}</div>'.format(content=html)
        return html

    def list_to_class(self, html, klass):
        klass = self.CUSTOM_CONTROL_CLASS.get(klass, klass)
        html = super().list_to_class(html, klass)
        html = html.replace('class=""', 'class="custom-control-input"')
        return html

    radio_list_to_class = list_to_class

And i can update FieldRenderer with same logic (using beatyfulsoup for list_to_class), and add option like "use_custom_select/use_custom_radio". (or maybe select_css_class/radio_css_class) if it makes more sense.

What do you think?

last-partizan commented 5 years ago

https://github.com/last-partizan/django-bootstrap4/commit/834212046106636aded8dcebdd056fcc695d2079

Here is how it looks like.

aidanlister commented 4 years ago

I'd like custom-select support too. I'd want the API to look like:

{% bootstrap_field form.type show_label=False addon_after_class='' input_class='custom-select' %}

SebCorbin commented 4 years ago

Hello there, I'd really like to see this implemented in django-bootstrap4 and I'm glad someone has something functional.

Here's a list:

Checkboxes, Radios and Select should be fairly easy but I suggest implementing the rest through their own PR.

I like the idea to be able to set this globally, but should we handle an option like custom_element=True on the bootstrap_field tag?

What's the next step after https://github.com/last-partizan/django-bootstrap4/commit/834212046106636aded8dcebdd056fcc695d2079? Would it be enough for a PR?

dennohpeter commented 3 years ago

I'd like custom-select support too. I'd want the API to look like:

{% bootstrap_field form.type show_label=False addon_after_class='' input_class='custom-select' %} Is this now supported ? I really need input_class paramater too