pallets-eco / pallets-eco/wtforms

Select Fields should support disabled option out of the box

Open
#928 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.6k
Forks
409
PR merge metrics
No merged PRs in 30d

Description

While implementing multiple log-in systems I noticed that there's no way to implement disabled select options without significant effort on routes and templating.

Would a solution inside flask-wtf be appreciated if I make a PR and what would be the desired approach?

Below the solution I took.

Frontend

Image

Required Code

# forms.py
# Admin Log-in form for admin interface
class AdminLoginForm(FlaskForm):
    admin_login_username = StringField('Admin User', validators=[DataRequired()])
    admin_login_password = PasswordField('Admin Password', validators=[DataRequired()])
    admin_login_rememberme = BooleanField('Remember Me')
    # Currently only PAM, for future use when we add LDAP/AD support can be enabled to selectable realms
    admin_login_realm_options = [
        ("pam", "Linux PAM Standard Authentication"),
        ("ldap", "LDAP"),
        ("ad", "Active Directory"),
    ]
    admin_login_realms_enabled = {"pam"}  # only PAM is allowed for now, but this can be easily extended in the future

    admin_login_realm = SelectField(
        "Authentication Realms",
        choices=admin_login_realm_options,
        validators=[DataRequired()]
    )

    admin_login_submit = SubmitField('Sign In')

    def validate_admin_realm(self, field):
        if field.data not in self.admin_login_realms_enabled:
            raise ValidationError("Selected authentication method is not enabled.")
# routes.py
@ssldeploy.route('/admin/', methods=['GET', 'POST'])
def admin():
    brand = {'brandname' : 'companyname'}
    form = AdminLoginForm()
    if form.validate_on_submit():
        flash('Login requested for user {}, remember_me={}'.format(
            form.admin_login_username.data, form.admin_login_rememberme.data))
        return redirect('/')
    return render_template('admin/adminlogin.html', title='SSL Deploy Admin Interface', brand=brand, form=form)
<!-- Select Form Field Start -->
                    <select id="{{ form.admin_login_realm.id }}" name="{{ form.admin_login_realm.name }}" class="loginformfieldrealm">
                    {% for value, label in form.admin_login_realm.choices %}
                    {% set disabled = value not in form.admin_login_realms_enabled %}
                        <option value="{{ value }}"
                        {% if form.admin_login_realm.data == value %}selected{% endif %}
                        {% if disabled %}disabled class="text-gray-400"{% endif %}>
                        {{ label }}{% if disabled %} (disabled){% endif %}
                        </option>
                    {% endfor %}
                    </select>
<!-- Select Form Field END -->

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing SelectField and how its choices are rendered into the HTML select and option elements. Compare that path with the forms.py, routes.py, and template example in the issue. Done should provide a supported way to mark selected options disabled out of the box while retaining appropriate server-side validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
html, python
Domain
frontend, web-dev
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.