8

I would like Flask's "SubmitField" to use

<button type="submit" title="Save this form"><span>Save</span></button>

Instead of:

<input type="submit" title="Save this form" />

I am printing it out in templates:

{{ field(class=css_class, title=field.description, **kwargs) }}

I'm guessing that I have to somehow modify SubmitInput (the widget behind SubmitField), but I'm not sure how to do that exactly, do I somehow have to modify __html__()?

EDIT:

from flask.ext.wtf import Required, Length, EqualTo, Field, TextInput
from flask import Markup
class InlineButtonWidget(object):
    html = """
    <button type="submit" title="%s"><span>%s</span></button>
    """

    def __init__(self, input_type='submit'):
        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 HTMLString(self.html % (field.name, field.label ))


class InlineButton(Field):
  widget = InlineButtonWidget()
  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('sign up')

I want to be able to do this:

submit = InlineButton({'name' : 'submit', 'title' : 'sign up today for prizes.', 'type' : 'submitfieldtype', 'textInsideSpan' : 'Save Current Work' })

Paco
  • 4,520
  • 3
  • 29
  • 53
Dexter
  • 6,170
  • 18
  • 74
  • 101

2 Answers2

7

It's easy. You can create new widget like InlineButtonWidget() but I think it's better to remove submit from the form and use this in the template:

<button type="submit" title="Save this form"><span>Save</span></button>

Of course, you can work with this too:

{% for name, label in buttons %}
    <button type="submit" title="{{name}}"><span>{{name}}</span></button>
{% endfor %}

Sample widget:

class InlineButtonWidget(object):
    html = """
    <button type="submit" title="%s"><span>%s</span></button>
    """
    
    def __init__(self, input_type='submit'):
        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 HTMLString(self.html % (field.name, field.lable ))
SimonB
  • 325
  • 4
  • 13
Mohammad Efazati
  • 4,812
  • 2
  • 35
  • 50
  • 1
    I wish there was better flask-wtf documentation. I can't seem to use the widget properly. I'm trying to build a Field-derived class that uses your class as a widget, but it isn't appearing on the page even though everything checks out fine. I'm gonna be building a lot of forms, and I don't want to have to use different templates every time, just a generic form.html – Dexter Jan 23 '13 at 23:17
  • This pre-existing "field" function in jinja2 templates doesn't work, it just prints my Widget as escaped-html instead of printing the actual html. I can't find any documentation on the "field" function in jinja2, why? – Dexter Jan 23 '13 at 23:33
  • @Dexter user {{safe}} filter in jinja2. for documentation i suggest you wtforms docs. not flask-wtf – Mohammad Efazati Jan 24 '13 at 09:58
  • Yes I am using wtforms docs, and it's not clear I need "safe". {{safe}} is used when printing html, you use field() when printing wtforms fields, such as TextField or SubmitField etc., they don't seem to need "safe" at all. – Dexter Jan 24 '13 at 15:43
  • I'm using field() as shown in the html above. It prints it out as text instead of html. Even though TextField, SubmitField, SelectField work fine using field(). – Dexter Jan 24 '13 at 18:43
  • @Dexter you use somethings like this? test = testy(_("test"), widget=InlineButtonWidget()) – Mohammad Efazati Jan 24 '13 at 18:47
  • @Dexter if not work try this {{ field(class=css_class, title=field.description, **kwargs|safe)}} – Mohammad Efazati Jan 24 '13 at 18:47
  • I didn't use the first one, but I made a dumby "inlineButtonField" class that inherits Field class, and has _value() and widget set to your class. Yes I'll try to the safe keyword, I was just confused since other default Fields in WTForms dont need it. I feel like something is wrong with your code's "self.html". If I could find an example WTForm Widget that has the html within it, that would be easier. – Dexter Jan 24 '13 at 18:59
  • 1
    I found an example online, and your call() function returns self.html, but theirs returns HTMLString(self.html). Could this be it? See: http://stackoverflow.com/questions/8463421/how-to-render-my-select-field-with-wtforms – Dexter Jan 24 '13 at 19:03
  • yeah so I have it sort of working but it is trying to display the label, but I don't want a label for my submit button. I put the code I used in the original-post. It's coming out messed up even though in templates I'm using field() and no label area is defined. – Dexter Jan 24 '13 at 20:09
  • Ok I think I solved it over here: http://stackoverflow.com/questions/14510630/wtforms-creating-a-custom-widget – Dexter Jan 24 '13 at 21:14
  • What's title for? – simanacci Jul 01 '17 at 18:13
0

Following implementation is more generic.

from wtforms.widgets.core import html_params
from wtforms.widgets import HTMLString

class InlineButtonWidget(object):
    """
    Render a basic ``<button>`` field.
    """
    input_type = 'submit'
    html_params = staticmethod(html_params)

    def __call__(self, field, **kwargs):
        kwargs.setdefault('id', field.id)
        kwargs.setdefault('type', self.input_type)
        kwargs.setdefault('value', field.label.text)
        return HTMLString('<button %s>' % self.html_params(name=field.name, **kwargs))


class InlineSubmitField(BooleanField):
    """
    Represents an ``<button type="submit">``.  This allows checking if a given
    submit button has been pressed.
    """
    widget = InlineButtonWidget()


class SignupForm(Form):
    name = TextField('Name', [Length(min=1, max=200)])
    submit = InlineSubmitField('sign up')
Pooja
  • 736
  • 1
  • 13
  • 29