title: WTForms creating a custom widget
body: <p>The WTForms documentation is woefully inadequate, they don't even show you one single example of a custom widget that isn't derived from another widget already.</p>
  
  <p>I am trying to make a button type, that isn't an <code>&lt;input&gt;</code> in html:</p>
  
  <pre><code>submit = InlineButton(name='submit', type='submit', title='Save this page', textWithinSpan='Save')
  </code></pre>
  
  <p>This is what I'm trying:</p>
  
  <pre><code>from flask.ext.wtf import Required, Length, EqualTo, Field, TextInput, html_params
  from flask import Markup
  
  class InlineButtonWidget(object):
    text = ''
    html_params = staticmethod(html_params)
  
    def __init__(self, input_type='submit', **kwargs):
      self.input_type = input_type
  
    def __call__(self, field, **kwargs):
      kwargs.setdefault('id', field.id)
      kwargs.setdefault('type', self.input_type)
      if 'value' not in kwargs:
          kwargs['value'] = field._value()
      return Markup('&lt;button type="submit" %s&gt;&lt;span&gt;%s&lt;/span&gt;&lt;/button&gt;' % (self.html_params(name=field.name, **kwargs), kwargs['textWithinSpan']))
  
  
  class InlineButton(Field):
    widget = InlineButtonWidget()
  
    def __init__(self, label='', **kwargs):
      self.widget = InlineButtonWidget('submit', label)
    def __call__(self, **kwargs):
      return self.widget(self, **kwargs)
    def _value(self):
      if self.data:
          return u', '.join(self.data)
      else:
          return u''
  
  
  class SignupForm(Form):
      name = TextField('Name', [Length(min=1, max=200)])
      submit = InlineButton(name='submit', type='submit', title='Save this page', textWithinSpan='Save')
  </code></pre>
  
  <p>I shouldn't even need a Field derived object. But it doesn't display when you only use Widget by itself.</p>
  
  <p>And when you use the Field object, then it gives you all sorts of invalid parameter errors.</p>
  
  <p>Even delving into the WTForms source code makes it difficult to understand why it won't pass Kwargs from form to widget.</p>
  
  <p><strong>--- UPDATE ---</strong></p>
  
  <p>Ok, after I submit the question I basically figured out a workable solution:</p>
  
  <pre><code>class InlineButtonWidget(object):
      html_params = staticmethod(html_params)
  
      def __init__(self, input_type='submit', text=''):
          self.input_type = input_type
          self.text = text
  
      def __call__(self, field, **kwargs):
          kwargs.setdefault('id', field.id)
          kwargs.setdefault('type', self.input_type)
          if 'value' not in kwargs:
              kwargs['value'] = field._value()
          return Markup('&lt;button type="submit" %s&gt;&lt;span&gt;%s&lt;/span&gt;&lt;/button&gt;' % (self.html_params(name=field.name, **kwargs), field.text))
  
  
  class InlineButton(Field):
    widget = InlineButtonWidget()
  
    def __init__(self, label=None, validators=None, text='Save', **kwargs):
      super(InlineButton, self).__init__(label, validators, **kwargs)
      self.text = text
  
    def _value(self):
          if self.data:
              return u''.join(self.data)
          else:
              return u''
  
  
  
  class SignupForm(Form):
      name = TextField('Name', [Length(min=1, max=200)])
      submit = InlineButton('submit', text='Save', description='Save this')
  </code></pre>