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

Issues with Django-multiselectfield #5

Open
XeonZenn opened this issue Apr 14, 2021 · 1 comment
Open

Issues with Django-multiselectfield #5

XeonZenn opened this issue Apr 14, 2021 · 1 comment

Comments

@XeonZenn
Copy link

XeonZenn commented Apr 14, 2021

Hello!

So this is a little bit of a hacky fix because I don't fully understand the library.

It fixed my issue for https://pypi.org/project/django-multiselectfield/
it renders as a CheckboxSelectMultiple

line 286:
add

elif isinstance(widget, CheckboxSelectMultiple):
            classes = add_css_class(classes, "form-group", prepend=True)

To

def add_class_attrs(self, widget=None):
        if widget is None:
            widget = self.widget
        classes = widget.attrs.get("class", "")
        if ReadOnlyPasswordHashWidget is not None and isinstance(widget, ReadOnlyPasswordHashWidget):
            # Render this is a static control
            classes = add_css_class(classes, "form-control-static", prepend=True)
        elif not isinstance(widget, self.WIDGETS_NO_FORM_CONTROL):
            classes = add_css_class(classes, "form-control", prepend=True)
            # For these widget types, add the size class here
            classes = add_css_class(classes, self.get_size_class())
        elif isinstance(widget, CheckboxInput):
            classes = add_css_class(classes, "form-check-input", prepend=True)
        elif isinstance(widget, CheckboxSelectMultiple):
            classes = add_css_class(classes, "form-group", prepend=True)
        elif isinstance(widget, Select):
            classes = add_css_class(classes, "form-select", prepend=True)

line 332:
add

for input in enclosing_div.find_all("input"):
                try:
                    if not 'form-check-input' in input.attrs.get("class"):
                        input.attrs["class"] = input.attrs.get("class", []) + ["form-check-input"]
                except AttributeError:
                    pass

To

def list_to_class(self, html, klass):
        classes = add_css_class(klass, self.get_size_class())
        mapping = [
            ("<ul", '<div class="{classes}"'.format(classes=classes)),
            ("</ul>", "</div>"),
            ("<li", '<div class="{form_check_class}"'.format(form_check_class=self.form_check_class)),
            ("</li>", "</div>"),
        ]
        for k, v in mapping:
            html = html.replace(k, v)

        # Apply bootstrap5 classes to labels and inputs.
        # A simple 'replace' isn't enough as we don't want to have several 'class' attr definition, which would happen
        # if we tried to 'html.replace("input", "input class=...")'
        soup = BeautifulSoup(html, features="html.parser")
        enclosing_div = soup.find("div", {"class": classes})
        if enclosing_div:
            for label in enclosing_div.find_all("label"):
                label.attrs["class"] = label.attrs.get("class", []) + ["form-check-label"]
                try:
                    label.input.attrs["class"] = label.input.attrs.get("class", []) + ["form-check-input"]
                except AttributeError:
                    pass
            for input in enclosing_div.find_all("input"):
                try:
                    if not 'form-check-input' in input.attrs.get("class"):
                        input.attrs["class"] = input.attrs.get("class", []) + ["form-check-input"]
                except AttributeError:
                    pass
        return str(soup)

line 379
change
html = self.list_to_class(html, "checkbox")

to
html = self.list_to_class(html, "form-group")

in

def post_widget_render(self, html):
        if isinstance(self.widget, RadioSelect):
            html = self.list_to_class(html, "radio radio-success")
        elif isinstance(self.widget, CheckboxSelectMultiple):
            html = self.list_to_class(html, "form-group")
        elif isinstance(self.widget, SelectDateWidget):
            html = self.fix_date_select_input(html)
        elif isinstance(self.widget, CheckboxInput) and self.show_label:
            html = self.add_checkbox_label(html)
        elif isinstance(self.widget, FileInput):
            html = self.fix_file_input_label(html)
        return html

renderers.py.txt

@XeonZenn XeonZenn changed the title Doesn't render a Multicheckbox input correctly Issues with Django-multiselectfield Apr 14, 2021
@zelenij
Copy link
Owner

zelenij commented May 1, 2021

Thanks for pointing this out. I'd appreciate if you could add a PR with your proposed changes - you are 3/4 way there already! Then I'll be happy to review and merge.

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

2 participants