What is the simplest way to assign 'disabled' html attribute to one of the options in SelectField in WTForms?
This is my previous code
<select class="form-control" name="division" data-error="Required!" required>
<option value="default" disabled selected>Select something</option>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
As you can see I would like to set 'disabled' only to first option.
My code for this task is:
next(form.division.__iter__())(**{'disabled':'true'})
And using print function in console I can see the proper output:
<option disabled="true" selected value="default">Select something</option>
The line is working, but somehow this output is not passed to the template. Instead this is what's passed:
<option selected value="default">Select something</option>
Please someone make it clear.
Here's a custom wtforms widget which makes use of the SelectField's Options iterator.
from markupsafe import Markup
from wtforms.widgets.core import html_params
class CustomSelect:
"""
Renders a select field allowing custom attributes for options.
Expects the field to be an iterable object of Option fields.
The render function accepts a dictionary of option ids ("{field_id}-{option_index}")
which contain a dictionary of attributes to be passed to the option.
Example:
form.customselect(option_attr={"customselect-0": {"disabled": ""} })
"""
def __init__(self, multiple=False):
self.multiple = multiple
def __call__(self, field, option_attr=None, **kwargs):
if option_attr is None:
option_attr = {}
kwargs.setdefault("id", field.id)
if self.multiple:
kwargs["multiple"] = True
if "required" not in kwargs and "required" in getattr(field, "flags", []):
kwargs["required"] = True
html = ["<select %s>" % html_params(name=field.name, **kwargs)]
for option in field:
attr = option_attr.get(option.id, {})
html.append(option(**attr))
html.append("</select>")
return Markup("".join(html))
When declaring the field, pass an instance of CustomSelect
as the widget
parameter.
division = SelectField(
"Division",
choices=[("default", "Select something"), ("option1", "Option 1"), ("option2", "Option 2")],
validators=[InputRequired()],
widget=CustomSelect(),
default="default",
)
And to pass attributes when rendering
form.division(option_attr={"division-0": {"disabled": ""} }, class="form-control")
If you simply just want a disabled and selected option as the first option of your select, I found this to be simpler than extending the SelectField class:
Just loop over the option and check for first loop iteration
<select name="my_select" id="my_select">
{% for option in form.my_select %}
{% if loop.first %}
<option value="" disabled selected>select something</option>
{% endif %}
{{ option }}
{% endfor %}
</select>
When you disable the field the values are no longer passed. What you might want to do is pass the variable by using read only instead of disabled. Here's how do to it with jquery :
$('#id_of_option').prop('readonly', true);
Also what I've done is set choices in Wtforms where
choices = [('', 'please select an option'), ('1', 'option 1'), ('2', 'option 2')]
and this way a user has to select a value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With