Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

SelectField - can choices tuples be expanded to allow for tooltips #692

Closed
adam-rehin opened this issue May 21, 2021 · 1 comment · Fixed by #739
Closed

SelectField - can choices tuples be expanded to allow for tooltips #692

adam-rehin opened this issue May 21, 2021 · 1 comment · Fixed by #739
Labels
enhancement New feature, or existing feature improvement

Comments

@adam-rehin
Copy link

At present the choices list should contain tuples:
[ ("option-value", "display-text"), (..., ...), ... ]

Can it be expanded to optionally allow a tool-tip as 3rd tuple element which is then rendered as a title attribute in the element:
("option-value", "display-text", "tool-tip") --> <option value="optional-value" title="tool-tip">display-text</option>

@augnustin
Copy link

augnustin commented Jun 3, 2021

I found the solution there: https://stackoverflow.com/questions/23460857/create-selectfield-options-with-custom-attributes-in-wtforms

Here's the code:

from wtforms.fields  import SelectField
from wtforms.widgets import Select, html_params, HTMLString

class SelectWithOptions(Select):
    """
    Renders a select field that supports options including additional html params.

    The field must provide an `iter_choices()` method which the widget will
    call on rendering; this method must yield tuples of
    `(value, label, selected, html_attribs)`.
    """

    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, html_attribs in field.iter_choices():
            html.append(self.render_option(val, label, selected, **html_attribs))
        html.append('</select>')
        return HTMLString(''.join(html))

class SelectWithOptionsField(SelectField):
    widget = SelectWithOptions()

    @property
    def current_choice(self):
        if self.data:
          return next(choice for choice in self.choices if int(choice[0]) == int(self.data))
        else:
          return self.choices[0]

    def iter_choices(self):
        for value, label, render_args in self.choices:
            yield (value, label, self.coerce(value) == self.data, render_args)

    def pre_validate(self, form):
         if self.choices:
             for v, _, _ in self.choices:
                 if self.data == v:
                     break
             else:
                 raise ValueError(self.gettext('Is Not a valid choice'))

Usage:

Country = SelectWithOptionsField('Country', choices=[(c.id, c.name, {'title': c.name}) for c in Country.query.all()])

Though I agree, a render_option param should be available in the SelectField attributes.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
enhancement New feature, or existing feature improvement
Development

Successfully merging a pull request may close this issue.

3 participants