The Themosis framework provides a new form class to help you build HTML forms. It includes methods to construct the form inner fields, methods for validation and error reporting by leveraging the illuminate/validation package.

You can add as many fields as you want to your form. Each added field has shared as well as unique properties and render its own HTML thanks to a view file attached to it.

In order to add a field to your form, you may use the add method on your form and use the FieldFactoryInterface instance to pass a field instance to it. Based on our ContactForm example, let's add a text input for full name, an email input, a textarea input and a submit button:

The form API automatically prefix your input name attribute values in order to avoid conflict with WordPress restricted query vars. You could use a name value for your field for example and it will render by default with a name attribute of th_name.

The default prefix is th_ but you can provide your own form prefix as well.

Our contact form example does not yet handle input validation as no rules have been defined on the fields. Let's add some basic validation rules to our form fields!

Once you add validation rules to your form fields, error reporting is not enabled by default. In order for validation to work, you must pass a Request object to your form. Please read the error reporting section below for more details regarding validation.

The form handles validation as well as error reporting. By default, if a field validation failed, the form has a not valid status and the field, if rendered back to a view, is rendering an error message below its input.

In order to trigger validation on a form, you need to pass it the Request instance. All controllers methods can capture a Request instance by type-hinting it as one of the method argument.

Following our ContactForm sample, let's enable validation on the form by calling the form handleRequest method like so from a controller method listening on a POST request:

The above code will receive sent data through the Request instance. The request object is then pass to the form using the handleRequest method.

Validation is done directly on the handleRequest method. So in the above example, we don't do anything special with the submitted data. The form instance is sent back to the same contact view and render its content on a POST request.

If validation is successful, the form is flushing all its data by default. So the rendered page is an empty form. If the validation failed, the form will keep valid data and flush invalid one. For fields where validation failed, the form is also rendering an error message below each field.

After calling the form handleRequest method, the form changes its internal state. If validation is successful after passing the Request instance, you can call the form isValid method to perform action like so:

For now, the form instance is not yet managing form data through a value object instance. This solution is a temporary approach to retrieve form valid data after a successful validation.

As mentioned above, each time a validation is successful on a form, the object flush its field data. In order to avoid losing validated data after validation, you can pass a flush option to your form make method like so:

All validation rules have an error message attached to them by default. The list of errors messages is stored at application root inside the resources/languages/en_US/validation.php file.

Note that the framework is also providing error messages in french for France within the fr_FR directory and for Belgium in the fr_BE folder.

The validation.php file is a global list of messages for your application. You could customize your form error messages from there but please note that any change applied inside that validation file is applicable on all your application forms: front-end forms, metabox fields, page settings, ...

If you want to customize the error message for your form, it is best to pass a messages option to your field. The messages option accept an array of key/value pairs where the key is the name of the validation rule and its value, the validation message.

For example, let's customize the errors messages for the contact form:

Note the use of the :attribute placeholder. This attribute placeholder is replaced by the field name (without its prefix) inside the message. So, based on the example above, the full name minimum message is: "Your fullname should contain 3 characters at least."

You can also customize the value of the :attribute placeholder. You can change the attribute value by passing a placeholder option to your field like so:

By default, a form instance is organizing all attached fields to a default group. Think of a form group as a form section containing its own inner fields. At render time, each group is also contained in its own div element.

After validation, you may access the form valid data in order to perform specific actions. The recommended approach is to use a "data object" representing the form data or by using the form fields repository instance in order to fetch fields objects and retrieve their value individually.

By default, a form instance will try to map all defined fields to a property of a data object. If you do not want to map a field to your DTO object, you can set its mapped option to false.

The form class is leveraging the Symfony property access component. A data object can manage its internal state using public properties or getters and setters. Here is an example of the CreatePostData object using public properties:

You can control the form tag HTML attributes by passing an attributes option to your form and passing an array of key/value pairs. The key is representing the HTML attribute name and the value the attribute value.

You can, for example, specify the action attribute value of your form in order to send the request to another URL like so:

The errors option allows you to inform the form to display or not the errors messages after validation. By default, after a failed validation, if you render the form, each field is displaying its error message below its input. If you want to control where to display form errors on your page, then you can set the errors option to false and then leverage the errors method of your form instance to get the list of messages to display.

return $factory->make(null, [
'errors' => false
])
...
->get();

By setting the errors option to false, your form is no longer displaying errors messages. Use the form errors method to fetch the messages like so:

The flush option, as already mentioned, allows you to remove or not validated data after a successful validation. By default the value is set to true meaning that the data is removed upon validation. If you want to persist the data in your form instance, set the flush option value to false.

By default, all form instances generate a WordPress nonce field. By default, the nonce name is set to _themosisnonce with a default action value of form.

It is best to customize the nonce field per form. You can do so by providing a nonce and/or a nonce_action options to your form instance. Generally, you may want to keep the default nonce name _themosisnonce but it is recommended to change the action verb like so:

The tags option controls the output of the form HTML tags. If for example, your form should be embedded inside an existing form (for example, inside a WordPress administration page), you may need to output only its fields by setting the tags option to false like so:

A form and its fields are rendered through a group of pre-defined views. Each group of views is a theme. By default, each form is rendered using the themosis theme which output the HTML tags with custom CSS classes in order to customize the look of your form.

The framework also handles a bootstrap theme, which output form elements using the BootstrapCSS classes. In order to change the form theme, simply provide a theme option with the group name as a value like so:

return $factory->make(null, [
'theme' => 'bootstrap'
])
...
->get();

When a theme is applied from the form, the theme is applied to its inner fields directly.

In the above example, the last name, first name and email fields are grouped under the main group while other fields are grouped to the default one. The group name is arbitrary. The API is grouping fields based on a similar group name.

You can then render the form inside your view using the render method:

{!! $form->render() !!}

Based on the above example, the first 3 fields are wrapped in a separate div element.