0
# Form Rendering
1
2
Comprehensive form rendering capabilities with Bootstrap styling, supporting multiple layout types, validation error display, field grouping, and extensive customization options for Flask-WTF/WTForms integration.
3
4
## Capabilities
5
6
### Complete Form Rendering
7
8
Render entire forms with Bootstrap styling and automatic validation error handling.
9
10
```python { .api }
11
def render_form(form, action="", method="post", extra_classes=None, role="form",
12
form_type="basic", horizontal_columns=('lg', 2, 10), enctype=None,
13
button_map={}, button_style="", button_size="", id="",
14
novalidate=False, render_kw={}, form_group_classes="",
15
form_inline_classes=""):
16
"""
17
Render a complete form with Bootstrap styling.
18
19
Args:
20
form: WTForms form object
21
action (str): Form action URL (default: current URL)
22
method (str): HTTP method (default: "post")
23
extra_classes (str): Additional CSS classes for form element
24
role (str): ARIA role attribute (default: "form")
25
form_type (str): Layout type - "basic", "inline", or "horizontal"
26
horizontal_columns (tuple): Column sizing for horizontal layout (breakpoint, label_cols, field_cols)
27
enctype (str): Form encoding type (auto-detected for file uploads)
28
button_map (dict): Custom button styles per field name
29
button_style (str): Default button style for submit buttons
30
button_size (str): Default button size for submit buttons
31
id (str): Form element ID attribute
32
novalidate (bool): Disable HTML5 validation
33
render_kw (dict): Additional attributes for form element
34
form_group_classes (str): Classes for form groups (Bootstrap 5)
35
form_inline_classes (str): Classes for inline forms (Bootstrap 5)
36
37
Returns:
38
Rendered HTML form with Bootstrap styling
39
40
Layout Types:
41
- basic: Standard vertical form layout
42
- inline: Horizontal inline form layout
43
- horizontal: Two-column layout with labels and fields
44
"""
45
```
46
47
### Individual Field Rendering
48
49
Render individual form fields with Bootstrap styling and validation states.
50
51
```python { .api }
52
def render_field(field, form_type="basic", horizontal_columns=('lg', 2, 10),
53
button_map={}, button_style='', button_size='', form_group_classes=''):
54
"""
55
Render an individual form field with Bootstrap styling.
56
57
Args:
58
field: WTForms field object
59
form_type (str): Layout type - "basic", "inline", or "horizontal"
60
horizontal_columns (tuple): Column sizing for horizontal layout
61
button_map (dict): Custom button styles for this field
62
button_style (str): Default button style for submit/button fields
63
button_size (str): Default button size for submit/button fields
64
form_group_classes (str): Additional classes for form group (Bootstrap 5)
65
66
Returns:
67
Rendered HTML field with appropriate Bootstrap classes
68
69
Field Type Support:
70
- Text inputs (StringField, TextAreaField, etc.)
71
- Select fields (SelectField, SelectMultipleField)
72
- Boolean fields (BooleanField, SwitchField)
73
- File uploads (FileField, MultipleFileField)
74
- Hidden fields (HiddenField)
75
- Submit buttons (SubmitField)
76
- Custom field types
77
78
Validation Features:
79
- Automatic validation state classes (is-valid, is-invalid)
80
- Error message display
81
- Required field indicators
82
"""
83
```
84
85
### Multi-Column Form Rows
86
87
Render multiple fields in a single row using Bootstrap grid classes.
88
89
```python { .api }
90
def render_form_row(fields, row_class='row', col_class_default='col',
91
col_map={}, button_map={}, button_style='', button_size='',
92
form_group_classes='', form_type='basic',
93
horizontal_columns=('lg', 2, 10)):
94
"""
95
Render multiple form fields in a single row layout.
96
97
Args:
98
fields (list): List of WTForms field objects
99
row_class (str): CSS class for row container (default: 'row')
100
col_class_default (str): Default column class (default: 'col')
101
col_map (dict): Custom column classes per field name
102
button_map (dict): Custom button styles per field name
103
button_style (str): Default button style
104
button_size (str): Default button size
105
form_group_classes (str): Form group classes (Bootstrap 5)
106
form_type (str): Form layout type
107
horizontal_columns (tuple): Horizontal form column configuration
108
109
Returns:
110
Rendered HTML row with fields in Bootstrap grid layout
111
112
Example col_map:
113
{
114
'first_name': 'col-md-6',
115
'last_name': 'col-md-6',
116
'email': 'col-12'
117
}
118
"""
119
```
120
121
### Hidden Field Error Handling
122
123
Render validation errors for hidden form fields.
124
125
```python { .api }
126
def render_hidden_errors(form):
127
"""
128
Render validation errors for hidden form fields.
129
130
Args:
131
form: WTForms form object
132
133
Returns:
134
Rendered HTML alert with hidden field errors
135
136
Used for displaying validation errors from hidden fields like CSRF tokens
137
that users cannot see but may have validation issues.
138
"""
139
```
140
141
### Switch Field Component
142
143
Custom field type for Bootstrap switch components.
144
145
```python { .api }
146
class SwitchField(BooleanField):
147
"""
148
A wrapper field for BooleanField that renders as a Bootstrap switch.
149
150
Inherits all BooleanField functionality but renders with switch styling
151
instead of standard checkbox appearance.
152
"""
153
154
def __init__(self, label=None, **kwargs):
155
"""
156
Initialize switch field.
157
158
Args:
159
label (str): Field label
160
**kwargs: Additional field arguments passed to BooleanField
161
"""
162
```
163
164
## Form Layout Types
165
166
### Basic Layout
167
168
Standard vertical form layout with fields stacked vertically.
169
170
```html
171
<!-- Template usage -->
172
{% from 'bootstrap5/form.html' import render_form %}
173
{{ render_form(form, form_type="basic") }}
174
175
<!-- Rendered output structure -->
176
<form method="post" role="form">
177
<div class="mb-3">
178
<label class="form-label">Username</label>
179
<input type="text" class="form-control" name="username">
180
</div>
181
<div class="mb-3">
182
<label class="form-label">Password</label>
183
<input type="password" class="form-control" name="password">
184
</div>
185
<button type="submit" class="btn btn-primary">Submit</button>
186
</form>
187
```
188
189
### Inline Layout
190
191
Horizontal inline form layout with fields arranged side-by-side.
192
193
```html
194
<!-- Template usage -->
195
{{ render_form(form, form_type="inline") }}
196
197
<!-- Rendered output structure (Bootstrap 5) -->
198
<form method="post" role="form" class="row row-cols-lg-auto g-3 align-items-center">
199
<div class="col">
200
<label class="visually-hidden">Username</label>
201
<input type="text" class="form-control" name="username" placeholder="Username">
202
</div>
203
<div class="col">
204
<label class="visually-hidden">Password</label>
205
<input type="password" class="form-control" name="password" placeholder="Password">
206
</div>
207
<div class="col">
208
<button type="submit" class="btn btn-primary">Submit</button>
209
</div>
210
</form>
211
```
212
213
### Horizontal Layout
214
215
Two-column layout with labels and fields in separate columns.
216
217
```html
218
<!-- Template usage -->
219
{{ render_form(form, form_type="horizontal", horizontal_columns=('lg', 2, 10)) }}
220
221
<!-- Rendered output structure -->
222
<form method="post" role="form">
223
<div class="row mb-3">
224
<label class="col-lg-2 col-form-label">Username</label>
225
<div class="col-lg-10">
226
<input type="text" class="form-control" name="username">
227
</div>
228
</div>
229
<div class="row mb-3">
230
<label class="col-lg-2 col-form-label">Password</label>
231
<div class="col-lg-10">
232
<input type="password" class="form-control" name="password">
233
</div>
234
</div>
235
<div class="row">
236
<div class="col-lg-10 offset-lg-2">
237
<button type="submit" class="btn btn-primary">Submit</button>
238
</div>
239
</div>
240
</form>
241
```
242
243
## Validation and Error Handling
244
245
### Automatic Validation States
246
247
Bootstrap-Flask automatically applies validation classes based on field errors:
248
249
```html
250
<!-- Field with validation error -->
251
<div class="mb-3">
252
<label class="form-label">Email</label>
253
<input type="email" class="form-control is-invalid" name="email" value="invalid-email">
254
<div class="invalid-feedback">
255
Please enter a valid email address.
256
</div>
257
</div>
258
259
<!-- Field with valid input -->
260
<div class="mb-3">
261
<label class="form-label">Username</label>
262
<input type="text" class="form-control is-valid" name="username" value="john_doe">
263
<div class="valid-feedback">
264
Looks good!
265
</div>
266
</div>
267
```
268
269
### Multiple Error Messages
270
271
When a field has multiple validation errors, all are displayed:
272
273
```html
274
<div class="invalid-feedback">
275
<ul class="mb-0">
276
<li>This field is required.</li>
277
<li>Must be between 8 and 150 characters long.</li>
278
</ul>
279
</div>
280
```
281
282
## Usage Examples
283
284
### Basic Form Example
285
286
```python
287
# forms.py
288
from flask_wtf import FlaskForm
289
from wtforms import StringField, PasswordField, BooleanField, SubmitField
290
from wtforms.validators import DataRequired, Length, Email
291
292
class LoginForm(FlaskForm):
293
username = StringField('Username', validators=[DataRequired(), Length(1, 20)])
294
password = PasswordField('Password', validators=[DataRequired(), Length(8, 150)])
295
remember = BooleanField('Remember me')
296
submit = SubmitField('Sign In')
297
```
298
299
```html
300
<!-- template.html -->
301
{% from 'bootstrap5/form.html' import render_form %}
302
303
<div class="container">
304
<div class="row justify-content-center">
305
<div class="col-md-6">
306
<h2>Login</h2>
307
{{ render_form(form) }}
308
</div>
309
</div>
310
</div>
311
```
312
313
### Customized Form with Styling
314
315
```html
316
{% from 'bootstrap5/form.html' import render_form %}
317
318
{{ render_form(form,
319
form_type="horizontal",
320
horizontal_columns=('md', 3, 9),
321
button_style="success",
322
button_size="lg",
323
extra_classes="border p-4 rounded"
324
) }}
325
```
326
327
### Multi-Column Form Layout
328
329
```html
330
{% from 'bootstrap5/form.html' import render_form_row, render_field %}
331
332
<form method="post">
333
{{ form.hidden_tag() }}
334
335
<!-- Name fields in one row -->
336
{{ render_form_row([form.first_name, form.last_name],
337
col_map={'first_name': 'col-md-6', 'last_name': 'col-md-6'}) }}
338
339
<!-- Full-width email field -->
340
{{ render_field(form.email) }}
341
342
<!-- Address fields in one row -->
343
{{ render_form_row([form.address, form.city, form.zip_code],
344
col_map={'address': 'col-md-6', 'city': 'col-md-4', 'zip_code': 'col-md-2'}) }}
345
346
{{ render_field(form.submit) }}
347
</form>
348
```
349
350
### Switch Field Usage
351
352
```python
353
# forms.py
354
from flask_bootstrap import SwitchField
355
356
class SettingsForm(FlaskForm):
357
notifications = SwitchField('Enable notifications')
358
dark_mode = SwitchField('Dark mode')
359
auto_save = SwitchField('Auto-save documents')
360
```
361
362
```html
363
<!-- Renders as Bootstrap switches -->
364
{% from 'bootstrap5/form.html' import render_field %}
365
366
<div class="form-check form-switch">
367
{{ render_field(form.notifications) }}
368
</div>
369
```
370
371
### File Upload Forms
372
373
```python
374
# forms.py
375
from wtforms import FileField
376
from flask_wtf.file import FileRequired, FileAllowed
377
378
class UploadForm(FlaskForm):
379
file = FileField('Upload File', validators=[
380
FileRequired(),
381
FileAllowed(['jpg', 'png', 'pdf'], 'Images and PDFs only!')
382
])
383
submit = SubmitField('Upload')
384
```
385
386
```html
387
<!-- Automatically sets enctype="multipart/form-data" -->
388
{{ render_form(form) }}
389
```
390
391
### Custom Button Styling
392
393
```html
394
{{ render_form(form,
395
button_map={
396
'submit': 'btn-success btn-lg',
397
'cancel': 'btn-outline-secondary',
398
'delete': 'btn-danger'
399
}
400
) }}
401
```
402
403
### Bootstrap 4 vs Bootstrap 5 Differences
404
405
```html
406
<!-- Bootstrap 4 -->
407
{% from 'bootstrap4/form.html' import render_form %}
408
{{ render_form(form, form_type="inline") }}
409
410
<!-- Bootstrap 5 -->
411
{% from 'bootstrap5/form.html' import render_form %}
412
{{ render_form(form,
413
form_type="inline",
414
form_inline_classes="row row-cols-lg-auto g-3 align-items-center"
415
) }}
416
```
417
418
The main differences include updated CSS classes, form control styling, and enhanced accessibility features in Bootstrap 5.