Skip to content
New issue

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

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

Already on GitHub? Sign in 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.

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

Successfully merging a pull request may close this issue.

3 participants