Add a css class to a field in wtform
You actually don't need to go to the widget level to attach an HTML class attribute to the rendering of the field. You can simply specify it using the class_
parameter in the jinja template.
e.g.
{{ form.email(class_="form-control") }}
will result in the following HTML::
<input class="form-control" id="email" name="email" type="text" value="">
to do this dynamically, say, using the name of the form as the value of the HTML class attribute, you can do the following:
Jinja:
{{ form.email(class_="form-style-"+form.email.name) }}
Output:
<input class="form-style-email" id="email" name="email" type="text" value="">
For more information about injecting HTML attributes, check out the official documentation.
How to style WTForm fields using custom css classes?
The elements that are generated by wtforms
are different from those you were initially rendering. Some of your css selectors target elements that don't exist on the page anymore.
For example you used a button
for submitting the form before
<li><button class="active" type="submit" value="post">Post</button></li>
and you have a selector that targets this: .post-project-fields form ul li button
, but
{{ form.submit }}
# renders
<input id="submit" name="submit" type="submit" value="Post">
So create a selector that targets the input instead.
You could also make a more generic selector that targets any element that has a type
attribute of value "submit"
[type="submit"] {
color: #000000;
font-size: 16px;
border: 1px solid #e5e5e5;
padding: 10px 25px;
display: inline-block;
background-color: #d7d7d7;
font-weight: 600;
cursor: pointer;
}
Inspect the generated elements in the browser and create your styles around that.
Wtforms, add a class to a form dynamically
WTForms does not allow you to set display options (such as class name) in the field initialization. However, there are several ways to get around this:
If all of your fields should include a class name as well as an ID then just pass in each field's
short_name
to it when you render it:<dl>
{% for field in form %}
<dt>{{field.label}}</dt>
<dd>{{field(class_=field.short_name)}}</dd>
{% endfor %}
</dl>Create a custom widget mixin that provides the class name:
from wtforms.fields import StringField
from wtforms.widgets import TextInput
class ClassedWidgetMixin(object):
"""Adds the field's name as a class
when subclassed with any WTForms Field type.
Has not been tested - may not work."""
def __init__(self, *args, **kwargs):
super(ClassedWidgetMixin, self).__init__(*args, **kwargs)
def __call__(self, field, **kwargs):
c = kwargs.pop('class', '') or kwargs.pop('class_', '')
kwargs['class'] = u'%s %s' % (field.short_name, c)
return super(ClassedWidgetMixin, self).__call__(field, **kwargs)
# An example
class ClassedTextInput(ClassedWidgetMixin, TextInput):
pass
class Company(Form):
company_name = StringField('Company Name', widget=ClassedTextInput)
Add a CSS class to an option in a WTForms SelectField
If you look deep in the bowels of WTForms
you'll find a widget class called SelectField
this is the method called build the html string:
@classmethod
def render_option(cls, value, label, selected, **kwargs):
options = dict(kwargs, value=value)
if selected:
options['selected'] = True
return HTMLString('<option %s>%s</option>' % (html_params(**options), escape(text_type(label))))
this is __call__
method that invokes the render_options
function defined above.
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
if self.multiple:
kwargs['multiple'] = True
html = ['<select %s>' % html_params(name=field.name, **kwargs)]
for val, label, selected in field.iter_choices():
html.append(self.render_option(val, label, selected))
html.append('</select>')
return HTMLString(''.join(html))
You are not going to be able to add the class
attribute by simply instantiating a SelectField
. When you do this it creates the Option
instances implicitly. At render time the render_options
methods of these implicit instances are only invoked with val
, selected
, and label
arguments.
You can access the implicit Option
instances after the fact. This is not without issue. If you look at @Johnston's example:
>>> i = 44
>>> form = F()
>>> for subchoice in form.a:
... print subchoice(**{'data-id': i})
... i += 1
He is doing exactly this. But you have to provide the attributes to the class at render time. The invocation subchoice(**{'data-id': i})
actually spits out the expected HTML
. This poses quite the problem if you are integrating WTForms
with a template engine. Because the something like jinja
is calling these render functions for you.
If you want this type of behavior I would recommend writing your own implementation of SelectField
that allows you to pass attributes into the implicit Option
instances. This way the template engine can just go about the business of invoking render
and you can keep your definitions of the form consolidated in your forms.py
file(s)
Using Flask-WTForms, how do I style my form section of the html?
WTForms fields can be called with attributes that will be set on the input they render. Pass the attributes you need for styling, JavaScript functionality, etc. to the fields, rather than just referencing the fields. The labels behave the same way, and can be accessed with field.label
.
for
, value
, type
, id
, and name
do not need to be passed, as they are handled automatically. There are some rules for handling special cases of attributes. If an attribute name is a Python keyword such as class
, append an underscore: class_
. Dashes are not valid Python names, so underscores between words are converted to dashes; data_toggle
becomes data-toggle
.
{{ form.first_name(class_='validate') }}
{{ form.first_name.label(class_='active') }}
{{ form.begins(class_='datepicker', length=50) }}
Note that neither of the linked methods need to be called directly, those docs just describe the behavior when calling the fields.
Related Topics
Placing Unicode Character in CSS Content Value
How Do Min-Content and Max-Content Work
Css Selector - Element With a Given Child
How to Properly Display an Iframe in Mobile Safari
External CSS VS Inline Style Performance Difference
How to Determine What Font a Browser Is Actually Using to Render Some Text
How to Create Multi-Color Border With Css
Why ≪Textarea≫ and ≪Textfield≫ Not Taking Font-Family and Font-Size from Body
How to Display a Reverse-Ordered List in Html
My CSS Is Not Getting Injected Through My Content Script
Deprecated Smil Svg Animation Replaced with CSS or Web Animations Effects (Hover, Click)
@Import in @If Statement in SASS