Add a CSS Class to a Field in Wtform

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:

  1. 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>
  2. 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



Leave a reply



Submit