2

I am trying to create a dynamic form (within a python Flask application) using WTForms.

WTForms includes a FieldList field for lists of fields. I'd like to use this to make a form where users can add or remove items, e.g. specify different phone numbers.

Here is an example of a WTF solution using Ajax with WTForms and related question. These clone an existing form, and hence only work if there is at least one instance of the form already. I would like to remove this constraint to also allow an initially empty form.

I would like to use a javascript form plugin called SheepIt to dynamically add/remove widgets which does allow this, using a "form template" in the html.

Question is how to replace custom html in the "form template" such as:

<input id="phoneForm_#index#_number"
name="user[phones][#index#][number]" type="text"

with a WTF form field such as:

{% for phone in form.phones %}
  {{ phone.number }}
{% endfor %}

that allows the WTF goodies such as printing of form validation errors, etc. Problem here is I do not know if/where to place the above for loop when using a "template form" as done in SheepIt.

Community
  • 1
  • 1
Martijn Rutten
  • 763
  • 6
  • 14

1 Answers1

2

Flask's documentation suggests the following jinja2 macro for rendering WTForms fields:

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

To render subfields in a fieldlist, I use a slightly different version of this macro:

{% macro render_multi_field(field,field_name) %}
    <div class="form-group">
        {{ field_name }}
        {% for subfield in field %}
        <div class="base_class{% if subfield.errors %} error_class{% endif %}" id="{{subfield.name}}-group">
            {{ subfield(**kwargs)|safe }}
            <button data-field="{{ subfield.name }}-group">Remove Entry</button>
        </div>
        {% if subfield.errors %}
             {% for error in subfield.errors %}
                <p class="error_class">{{ error }}</p>
            {% endfor %}
        {% endif %}

        {% endfor %}
        <br/>
        <button type="button">Add entry</button>
    </div>
{% endmacro %}

I use this macro to render Fields with 0 to any number of entries. It allows error rendering, populating with default values and anything else you'd do with WTForms.

In my case, widgets are added / removed by javascript via the button in the macro.

iodbh
  • 688
  • 1
  • 7
  • 14
  • Can you please share the javscript code. I have problems to understand this. thank you – mthecreator Dec 05 '16 at 06:22
  • Hi @iodbh I'm trying to do something similar but for some reason my dynamically added entries don't retrieve the inputted data, could do with your advice, my question is here, cheers! https://stackoverflow.com/questions/45959882/macro-and-javascript-function-adds-fields-to-wtform-but-data-in-new-fields-is-n – nmh Aug 30 '17 at 12:28