Doing so will attach a text field, with one validator to the "Form"object. This module is intended for slightly more complex scenarios andto offer an easier way of configuration.

Also, this module, in its current state, is developed to scratch apersonal itch - simple server side validation of dynamic fields (throughWTForms itself). It is most likely missing some needed flexibilityand/or features, so do not hesitate to pinch in or drop me a line!

Quick overview--------------

Adding a field~~~~~~~~~~~~~~

The method *add\_field()* is used to add a field to the modulesconfiguration.

- Decorate field machine name arguments with %'s (%some\_field\_machine\_name) to have them automatically suffixed with a set number if applicable. More on this below.

Apply the configuration to a form~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Once you have setup your configuration using the above methods, you canapply it to any valid WTForm instance.

Usage: process(ValidFormClass(), POST)

Note that *POST* has to be a MultiDict, which is already the case withmost frameworks like Flask, Django, ...

Basic usage-----------

The idea behind this module is that you can add "dynamic" fields to aform that has already been created. "Dynamic" here means fields that arenot rendered (nor present in the original form object) initially, butget injected into the DOM afterwards.

The module uses the POST variables together with a user definedconfiguration to determine which fields are new and are allowed to beprocessed.

The first thing you need, obviously, is a valid WTForms instance to putthe new fields on. Say, for example, we have a form that contains afirst name and a last name field, this would be declared as follows:

When we present this form to our user, we wish to have the ability tooptionally add an email address and make it required once added.

In most cases, to make for a nice user experience, we go ahead an createa button that has some JavaScript bound to it which will inject the newemail input field. Also, because we all like instant feedback glory, wecould add some client side validation in our JavaScript to catchmistakes early and prevent a round trip to the server.

However, we also want this new email address field to be correctlyvalidated *on the server* and, in case when validation fails, berendered back to the user for inspection. We do not want to write ourown validation code for this field, but leverage the power of thealready present, full-blown WTForms form library to do the heavylifting.

This is where this module steps in.

First you will need an instance of the module:

.. code:: python

dynamic = WTFormDynamicFields()

Next you will need to build the configuration which will hold theallowed, dynamic fields (and their validators). To do this, you use the"add\_field" method: define the fields machine name, the label andfinally a WTForms field type:

.. code:: python

dynamic.add_field('email', 'Email address', TextField)

Optionally, you can pass \*args and \*\*kwargs to the field as well.

Of course, the machine name of the field needs to correspond with theinput's "name" attribute as injected by JavaScript. Also notice we donot add any parenthesis after the WTForms field type (TextField).

If needed, you can also apply optional validators by using the"add\_validator" method. You define on which field you wish to apply thevalidator and you pass in a WTForms validator:

.. code:: python

dynamic.add_validator('email', InputRequired, message='This field is required')

Here too you have the ability to pass in optional *args and *\ kwargs tothe validator. Again, no parenthesis after InputRequired, its argumentswill be bound by the module later on.

Now that you have added this email field and pushed a validator on it,you are ready to process your form. For the form to be processed, youwill need your original form (*PersonalFile* in our case) and the POSTthat comes back from the server.

Normally, you would bind your form variable directly to the WTForminstance:

.. code:: python

form = PersonalFile()

To enable this module to process you form, however, you simply need towrap its "process" method around it and add the incoming POST:

.. code:: python

form = dynamic.process(PersonalFile, request.post)

\*Note: the POST is expected to be a MultiDict data type (which is thecase with most frameworks like Flask, Django, ...).

Now the form will pick up the optional email field when injected andmake the validation fail server side if the field is left empty.Removing the field from the DOM will make your form pass validationagain (given that you filled in the first\_name and last\_name fields,that is).

Usage with sets===============

Now imagine the use case where you which to capture not one, but anundefined amount of email address in that same form and have them allvalidated correctly.

With WTForms Dynamic Fields, this is trivial as the module supports sets- multiple fields of the same kind. To support these sets in your forms,you only need to uphold a simple naming convention: "\_X" where X is anumber.

If we would add, say, four email fields, these HTML inputs would looklike this:

The fun fact is, you would not have to change anything to the code weused in the previous example. The module will derive the canonical nameof each field ("email" in this case) and apply the user definedconfiguration for the email field to each individually.

Advanced usage with sets========================

A more complex scenario could occur when you would have a set comprisedout of two or more fields that are dependent on one another.

For example, to elaborate on our email scenario from above, imagine wewish to also capture a telephone number with each email. But, to up thestakes, we only allow one of the two fields to be filled in.

This would require a dependency between the two fields - a validatorwhich checks if its field is filled in and the other one is not. Such avalidator would take the *other* field's name as an argument:

::

RequiredIfEmpty('email')

The above validator would be put on the "telephone" field to check ifthe email field was left empty.

Now if you have multiple sets of these fields, each field name will besuffixed with a number, like we have seen before:

The module detects when it is processing a set of fields (derived fromthe "*X" naming convention) and as such, when wrapping your field namewith % signs, will append the correct suffix to the field when bindingthe arguments to the validator. So if we would be looking at email*\ 4,once expanded, the above code will translate to: