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

Add support for FormField widget #66

Open
ahosgood opened this issue Jan 20, 2023 · 0 comments
Open

Add support for FormField widget #66

ahosgood opened this issue Jan 20, 2023 · 0 comments

Comments

@ahosgood
Copy link

There is currently no widget for the FormField (https://wtforms.readthedocs.io/en/2.3.x/fields/#field-enclosures) enclosure to group form fields.

Adding one would allow you to define small, reusable FlaskForm objects with a bunch of fields (kind of like a pattern). This should reduce duplicated code.

The initial code I produced to test this was:

from markupsafe import Markup
from wtforms.widgets.core import html_params


class GovukFieldsetWidget(object):
    def __init__(self):
        pass

    def construct_subfield(self, subfield, field, options):
        subfield_id = subfield.id.replace(field.id + field.separator, "")
        subfield_options = options[subfield_id] if subfield_id in options else {}
        return subfield.widget(subfield, params=subfield_options)

    def __call__(self, field, **kwargs):
        kwargs.setdefault("id", field.id)
        options = kwargs["params"] if "params" in kwargs else {}
        fieldset_options = {}
        html = ["<div class='govuk-form-group'>"]
        html.append("<fieldset class='govuk-fieldset' %s>" % (html_params(**fieldset_options)))
        field_title = (
            options["fieldset"]["legend"]["text"]
            if "fieldset" in options and "legend" in options["fieldset"] and "text" in options["fieldset"]["legend"]
            else field.label.text
            if field.label
            else field.name
            if field.name
            else ""
        )
        if field_title:
            fieldset_classes = (
                options["fieldset"]["legend"]["classes"]
                if "fieldset" in options
                and "legend" in options["fieldset"]
                and "classes" in options["fieldset"]["legend"]
                else ""
            )
            html.append("<legend class='govuk-fieldset__legend %s'>%s</legend>" % (fieldset_classes, field_title))
        if hasattr(field, "task_order"):
            for subfield_name in field.task_order:
                subfield = field[subfield_name]
                html.append(self.construct_subfield(subfield, field, options))
        else:
            for subfield in field:
                html.append(self.construct_subfield(subfield, field, options))
        html.append("</fieldset>")
        html.append("</div>")
        return Markup("".join(html))

You could then use the GovukFieldsetWidget to create a group of fields as a single form where that "pattern" could be validated separately:

from flask_wtf import FlaskForm
from wtforms.fields import IntegerField, FormField, BooleanField
from GovukFieldsetWidget import GovukFieldsetWidget # see class above
from govuk_frontend_wtf.wtforms_widgets import GovCheckboxInput, GovTextInput


class ChargeAmount(FlaskForm):
    class Meta:
        csrf = False

    task_order = ["charge_amount", "undisclosed_amount"]
    charge_amount = IntegerField(
        widget=GovTextInput(),
        validators=[],
    )
    undisclosed_amount = BooleanField(widget=GovCheckboxInput())


pattern = FormField(
    ChargeAmount,
    widget=GovukFieldsetWidget(),
)
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

1 participant