Constructing a wtforms\' TextAreaField is something like this:
content = wtf.TextAreaField(\'Content\', id=\"content-area\", validators=[validators.Required()])
You are not supposed to do it in the place where you declare the widget. You have do it in the template. For eg:
{{form.content(rows='50',cols='100')}}
Need to ensure the rows and cols are specified as a string.
You could simply use this replacement widget that is remembering default values for the rendering:
import wtforms.widgets.core
class TextArea(wtforms.widgets.core.TextArea):
def __init__(self, **kwargs):
self.kwargs = kwargs
def __call__(self, field, **kwargs):
for arg in self.kwargs:
if arg not in kwargs:
kwargs[arg] = self.kwargs[arg]
return super(TextArea, self).__call__(field, **kwargs)
Now you can add this new widget to your Field:
content = wtf.TextAreaField(
'Content',
id='content-area',
widget=TextArea(rows=50,cols=100),
validators=[validators.Required()])
You now can render this field without any extra arguments and get a 50x100 textarea.
Here is an example:
<div class="row">
<div class="col-md-12">
<div class="form-group">
{{ wtf.form_field(form.notes, rows=5) }}
</div>
</div>
</div>
I looked at the code and found that Field class defines both __new__
and __init__
. __new__
takes a bunch of *args
and **kargs
. So, you can just pass rows=x cols=y
in your TextAreadField creation and it should work. I noticed that wtforms is creating a class called "UnboundField" for such cases, I don't know the implications of that as where this would cause problems, if any. But the next step of creating the TextAreaField are same. (That is control goes to __init__
call as before.)
Much simpler; use render_kw
argument when creating the field:
port = IntegerField(u"HTTP port", validators=[DataRequired(), NumberRange(1025, 65535)], render_kw={'class': 'form-control'})
mytextarea = TextAreaField(u"Content", render_kw={'class': 'form-control', 'rows': 5})
And then render the file:
{{ field() }}
{{form.text(cols="35", rows="20")|safe}}
is working