diff --git a/docs/advanced.rst b/docs/advanced.rst
index 88e3023..eb32443 100644
--- a/docs/advanced.rst
+++ b/docs/advanced.rst
@@ -140,6 +140,34 @@ Bootstrap-Flask, simply use the built-in class ``SwitchField()`` instead of
``BooleanField()``. See also the example application.
+.. _inputcustomization:
+
+Form Input Customization
+------------------------
+
+Rendering Label
+~~~~~~~~~~~~~~~
+
+Bootstrap offers control for rendering
+`text `_. This is supported
+for inputs of a form by adding ``render_kw={'label_class': '... ...'}`` to the
+field constructor. In order to control the rendering of the label of a field,
+use ``render_kw={'label_class': '... ...'}``. See also the example application.
+
+Rendering Radio Label
+~~~~~~~~~~~~~~~~~~~~~
+
+Similar support exists for the rendering of the labels of options of a
+``RadioField()` with ``render_kw={'radio_class': '... ...'}``. See also the
+example application.
+
+Rendering Description
+~~~~~~~~~~~~~~~~~~~~~
+
+Use ``render_kw={'descr_class': '... ...'}`` for controlling the rendering of a
+field's description. See also the example application.
+
+
.. _bootswatch_theme:
Bootswatch Themes
diff --git a/docs/macros.rst b/docs/macros.rst
index 63f13db..78ba9a4 100644
--- a/docs/macros.rst
+++ b/docs/macros.rst
@@ -131,7 +131,7 @@ API
form group classes, it will read the config ``BOOTSTRAP_FORM_GROUP_CLASSES`` first
(the default value is ``mb-3``).
-.. tip:: See :ref:`button_customization` and :ref:`checkbox_customization` to learn more on customizations.
+.. tip:: See :ref:`button_customization`, :ref:`checkbox_customization` and :ref:`input_customization` to learn more on customizations.
render_form()
diff --git a/examples/bootstrap5/app.py b/examples/bootstrap5/app.py
index acb85b2..61d39db 100644
--- a/examples/bootstrap5/app.py
+++ b/examples/bootstrap5/app.py
@@ -31,10 +31,10 @@
class ExampleForm(FlaskForm):
"""An example form that contains all the supported bootstrap style form fields."""
- date = DateField(description="We'll never share your email with anyone else.") # add help text with `description`
- datetime = DateTimeField(render_kw={'placeholder': 'this is a placeholder'}) # add HTML attribute with `render_kw`
+ date = DateField()
+ datetime = DateTimeField(render_kw={'placeholder': 'this is a placeholder', 'class': 'fst-italic'})
datetime_local = DateTimeLocalField()
- time = TimeField()
+ time = TimeField(description="This isn't shared", render_kw={'descr_class': 'fs-1 text-decoration-underline'})
month = MonthField()
color = ColorField()
floating = FloatField()
@@ -45,7 +45,7 @@ class ExampleForm(FlaskForm):
url = URLField()
telephone = TelField()
image = FileField(render_kw={'class': 'my-class'}, validators=[Regexp('.+\.jpg$')]) # add your class
- option = RadioField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])
+ option = RadioField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')], render_kw={'label_class': 'text-decoration-underline', 'radio_class': 'text-decoration-line-through'})
select = SelectField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])
select_multiple = SelectMultipleField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])
bio = TextAreaField()
@@ -56,16 +56,30 @@ class ExampleForm(FlaskForm):
submit = SubmitField()
+class ExampleFormInline(FlaskForm):
+ """An example inline form."""
+ option = RadioField(description='Choose one', choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')], render_kw={'radio_class': 'text-decoration-line-through', 'descr_class': 'fw-bold'})
+ submit = SubmitField()
+
+
+class ExampleFormHorizontal(FlaskForm):
+ """An example horizontal form."""
+ floating = FloatField(description='a float', render_kw={'label_class': 'text-decoration-underline'})
+ integer = IntegerField(description='an int', render_kw={'descr_class': 'text-decoration-line-through'})
+ option = RadioField(description='choose 1', choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')], render_kw={'label_class': 'text-decoration-underline'})
+ submit = SubmitField()
+
+
class HelloForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(1, 20)])
password = PasswordField('Password', validators=[DataRequired(), Length(8, 150)])
- remember = BooleanField('Remember me')
+ remember = BooleanField('Remember me', description='Rember me on my next visit', render_kw={'descr_class': 'fw-bold text-decoration-line-through'})
submit = SubmitField()
class ButtonForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(1, 20)])
- confirm = SwitchField('Confirmation')
+ confirm = SwitchField('Confirmation', description='Are you sure?', render_kw={'label_class': 'font-monospace text-decoration-underline'})
submit = SubmitField()
delete = SubmitField()
cancel = SubmitField()
@@ -190,7 +204,9 @@ def test_form():
contact_form=ContactForm(),
im_form=IMForm(),
button_form=ButtonForm(),
- example_form=ExampleForm()
+ example_form=ExampleForm(),
+ inline_form=ExampleFormInline(),
+ horizontal_form=ExampleFormHorizontal()
)
diff --git a/examples/bootstrap5/templates/form.html b/examples/bootstrap5/templates/form.html
index b0b7b0a..70724dc 100644
--- a/examples/bootstrap5/templates/form.html
+++ b/examples/bootstrap5/templates/form.html
@@ -31,6 +31,14 @@
Example Form
submit = SubmitField()
{{ render_form(example_form) }}
+ Inline form
+ {% raw %}{{ render_form(inline_form, form_type='inline') }}{% endraw %}
+ {{ render_form(inline_form, form_type='inline') }}
+
+ Horizontal form
+ {% raw %}{{ render_form(horizontal_form, form_type='horizontal') }}{% endraw %}
+ {{ render_form(horizontal_form, form_type='horizontal') }}
+
Render a form with render_form
{% raw %}{{ render_form(form) }}{% endraw %}
{{ render_form(form) }}
diff --git a/flask_bootstrap/templates/bootstrap5/form.html b/flask_bootstrap/templates/bootstrap5/form.html
index e4d6e14..6551747 100644
--- a/flask_bootstrap/templates/bootstrap5/form.html
+++ b/flask_bootstrap/templates/bootstrap5/form.html
@@ -45,6 +45,23 @@
{% set form_group_classes = form_group_classes or config.BOOTSTRAP_FORM_GROUP_CLASSES %}
+ {# support for label_class and descr_class which are popped, to prevent they are added to input, but restored at the end of this macro for the next rendering #}
+ {%- set label_class = '' -%}
+ {%- if field.render_kw.label_class -%}
+ {% set label_class = field.render_kw.pop('label_class', '') -%}
+ {% set label_classes = ' ' + label_class -%}
+ {%- endif -%}
+ {%- set radio_class = '' -%}
+ {%- if field.render_kw.radio_class -%}
+ {% set radio_class = field.render_kw.pop('radio_class', '') -%}
+ {% set radio_classes = ' ' + radio_class -%}
+ {%- endif -%}
+ {%- set descr_class = '' -%}
+ {%- if field.render_kw.descr_class -%}
+ {% set descr_class = field.render_kw.pop('descr_class', '') -%}
+ {% set descr_classes = ' ' + descr_class -%}
+ {%- endif -%}
+
{# combine render_kw class or class/class_ argument with Bootstrap classes #}
{% set render_kw_class = ' ' + field.render_kw.class if field.render_kw.class else '' %}
{% set class = kwargs.pop('class', '') or kwargs.pop('class_', '') %}
@@ -68,14 +85,14 @@
{%- else -%}
{{ field(class="form-check-input%s" % extra_classes, **field_kwargs)|safe }}
{%- endif %}
- {{ field.label(class="form-check-label", for=field.id)|safe }}
+ {{ field.label(class="form-check-label%s" % label_classes, for=field.id)|safe }}
{%- if field.errors %}
{%- for error in field.errors %}
{{ error }}
{%- endfor %}
{%- elif field.description -%}
{% call _hz_form_wrap(horizontal_columns, form_type, required=required) %}
- {{ field.description|safe }}
+ {{ field.description|safe }}
{% endcall %}
{%- endif %}
@@ -85,12 +102,13 @@
this is just a hack for now, until I can think of something better #}