0
votes

New to using WTForms, and I can't figure out how to do expose additional form fields as shown here: https://css-tricks.com/exposing-form-fields-radio-button-css/

Because radio fields have the choices parameter where a list of fields is provided, is there any way to customize each of those choices? Like have something different be exposed when different choices are selected?

1

1 Answers

0
votes

This is going to be a mix of python and javascript code.

There are 2 common solutions:

  • Everything is already in the webpages and the unused fields are hidden until there is an action from the user (on the radio button).
  • Make API calls to get dynamic custom choices.

You can create a route:

@app.route("/api/choices", methods=["GET"])
def my route:
    custom_choices = get_custom_choices()
    return jsonify(custom_choices)

Then in your javascript code, when the user clicks on a button, you make a request to the this route to get the custom choices.

Then when you check/validate the sent form, populate the choices of the field with the custom choices (in the example, get_custom_choice) as described in the WTForms documentation here:

Note that the choices keyword is only evaluated once, so if you want to make a dynamic drop-down list, you’ll want to assign the choices list to the field after instantiation. Any submitted choices which are not in the given choices list will cause validation on the field to fail. If this option cannot be applied to your problem you may wish to skip choice validation (see below).

Select fields with dynamic choice values:

class UserDetails(Form):
    group_id = SelectField('Group', coerce=int)

def edit_user(request, id):
    user = User.query.get(id)
    form = UserDetails(request.POST, obj=user)
    form.group_id.choices = [(g.id, g.name) for g in Group.query.order_by('name')]

Note we didn’t pass a choices to the SelectField constructor, but rather created the list in the view function. Also, the coerce keyword arg to SelectField says that we use int() to coerce form data. The default coerce is str().

Source

The second solution requires more work, but it's lighter depending on how many different possibilities ou have for the choice. (And in my opinion: cleaner).