Drupal is a registered trademark of Dries Buytaert

schema_form

4 sites Security covered
View on drupal.org

This module automatically generates Drupal Forms directly from defined schemas, using the structure, labels and validation constraints from the schema definition.

It auto generates forms for configuration entities, config objects like module settings page, and for any other schema you want!

Simply put, to create a form page, you should only describe the data schema in a YAML schema file, and that's it. The form page will be generated automatically without custom code at all. But, if you need, you still can alter the form and add your customizations automatically on top of the auto-generated form.

Usage

Configuration forms

Let's imagine that you developed a custom API client that should store the API configuration and some options. So, you have to describe the schema in the file config/schema/my_module.schema.yml like this:

my_module.api_endpoint:
  type: config_object
  label: API Configuration
  mapping:
    endpoint:
      type: uri
      label: Endpoint
      constraints:
        NotBlank: []
    username:
      type: string
      label: Username
      constraints:
        Regex:
          pattern: /^[a-zA-Z0-9_]+$/
          message: Only alphanumeric characters and underscores are allowed.
    password:
      type: string
      label: Password
    debug_logging:
      type: boolean
      label: Enable debug logging

And then - you usually have to create a form, where have to list again the same list of fields and labels manually, then validate them and save to configs.

But with this module, you do not need to spend time on this! Just describe a route with the config name like this:

my_module.my_api_config:
  path: /admin/my-api-config
  defaults:
    _form: Drupal\schema_form\SchemaConfigFromRouteForm
    _title: My API config
  options:
    _admin_route: TRUE
    editable_config_names:
      - my_module.my_api_config
  requirements:
    _permission: administer system

The key part is the editable_config_names option where you can list one or more config names that should be exposed as a form. The rest will be done automatically by the module, you need just to open the configured url /admin/my-api-config and you will see the fully working form with all the fields, validation and configuration update functionality out of the box!

If you need to customize the page, create a simple class extending the Drupal\schema_form\SchemaConfigFormBase base class like this:

namespace Drupal\my_module\Form;

use Drupal\schema_form\SchemaConfigFormBase;

class MyConfigForm extends SchemaConfigFormBase {

  public function getEditableConfigNames() {
    return ['schema_form_test.my_config'];
  }

}

and then you can declare your own function buildForm(), validateForm() or submitForm() where to put your custom logic, and call the parent function to do the rest.

You can find more working examples in the tests/modules/schema_form_test submodule.

Config Entity forms

If you created a custom config entity, there is no need to create and manage the form class for it, the module will do this automatically. All that you need to do is just choose the the SchemaFormEntityForm class as a handler for the entity add and edit form like this:

use Drupal\schema_form\Form\SchemaFormEntityForm;

#[ConfigEntityType(
  id: 'my_custom_config_entity',
  ...
  handlers: [
    'form' => [
      'add' => SchemaFormEntityForm::class,
      'edit' => SchemaFormEntityForm::class,
      'delete' => EntityDeleteForm::class,
    ],
  ],
  ...
)]

And you can customize the form directly from the Drupal admin panel by creating a design on the page /admin/config/content/schema-form-design.

See a full example in the file src/Entity/SchemaFormDesign.php.

Regular forms

You can use this module not only for configuration forms, but for any form you want! So, instead of forming a long PHP array for the form, you just need to describe the schema and that's it. Here is an example:

my_module.my_feedback_form:
  type: mapping
  label: Send us your feedback
  mapping:
    first_name:
      type: string
      label: First name
    last_name:
      type: string
      label: Last name
    email:
      type: email
      label: Your email
      constraints:
        NotBlank: []
    message:
      type: text
      label: Message text
      constraints:
        NotBlank: []
      description: Please provide your feedback in this field.

And then - just create a simple class, extending the SchemaFormBase:

namespace Drupal\my_module\Form;

use Drupal\Core\Form\FormStateInterface;
use Drupal\schema_form\SchemaFormBase;

class MyFeedbackForm extends SchemaFormBase {
  public function getSchemaFormSchema(): string|null {
    return 'schema_form_test.my_feedback_form';
  }
  public function processSubmittedValues(TraversableTypedDataInterface $values, FormStateInterface $form_state): void {
    // Custom handling of already validated form submission typed values.
    $valuesArray = $values->getValue();
    $name = $valuesArray['first_name'] ?? NULL;
    $this->messenger()->addMessage($this->t('Thank you, @name!', [
      '@name' => $name ?? $this->t('Anonymous'),
    ]));
  }
}

And that's it! You have a fully working feedback form, without any PHP array filled manually! And you can just process the already validated and typed submission data, without handling this manually.

Look for more demo examples in the submodule tests/modules/schema_form_test.

To install the schema_form_test module on your local website, you need to add this line to the settings.php:

$settings['extension_discovery_scan_tests'] = TRUE;

Customizing the form

Classic PHP way

You can customize the form as usual by adding additional properties to the form elements in PHP, for example:

class MyFeedbackForm extends SchemaFormBase {
  ...
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);
    $form['first_name']['#description'] = $this->t("We'll be glad to know your name.");
    return $form;
  }
  ...
}

Schema Form Design in the Drupal admin panel

In the Drupal Admin panel, go to the Configuration » Content authoring » Schema Form designs (URL /admin/config/content/schema-form-design) and click on the "Add Schema Form Design" button.

There, type the id and the label of your design, and in the "Schema name" field - type your custom schema name.

Then, in the "Design" textarea put a list of "mapping" elements, where you can add or modify form elements with any data you want.

Schema inline way

And you can provide additional metadata directly in the Schema YAML structure like this:

my_module.my_feedback_form:
  type: schema_form
  label: Send us your feedback
  mapping:
    ...
    first_name:
      type: string
      label: First name
      description: We'll be glad to know your name.

In this example, we added the description. Yes, the 'description' field is not part of the Drupal Schema, but it is not restricted to use any additional fields in Drupal Schema YAML files, so the module uses this trick to simplify customizing the form. If you don't want to use this trick, you can always return to the classic way by customizing the pre-generated form array using PHP.

To avoid conflicts with other modules, the module supports the third_party_settings property that takes priority over other values:

my_module.my_form:
  type: mapping
  mapping:
    ...
    my_field:
      type: string
      label: My Field
      third_party_settings:
        schema_form:
          element:
            '#title': My Field Title
            '#description': My field description
            '#default_value': foo
            '#attributes':
              class:
                - my-field
            # And all other custom values for the form array element.

And for more convenience, it supports a simpler declaration of the common properties (title and description), like this:

my_module.my_form:
  type: mapping
  mapping:
    ...
    my_field:
      type: string
      label: My Field
      title: My Field Title # Here is a custom title, if you want to overwrite the schema item label for the form element. If it is filled, but the description is empty, the label is used as description.
      description: My field description # The field description text.

See more examples in the submodule directory tests/modules/schema_form_test.

Actually, Drupal Schema JSON format doesn't support non-standard properties and even third_party_settings, but they work without any problems, because the check is not strict. But there are no ways to attach additional metadata to the schema items, therefore - please vote on this issue #3522197 to add support for this.

Separate form declaration file

The module also will support a separate YAML file to declare the form specific additions to the data schema, to not mix the schema and the form representation in one place.

But the work on this feature is still in progress, please join the development.

Similar projects

Automatic Configuration Form - implements the same idea, but targeted only at configuration forms. Does not use plugins, so support is limited to only built-in field types.

Schema Based Config Forms - targeted only at configuration forms, extendable by plugins and provides more field types out of the box.

If you use those modules, you can simply replace them with this module Schema Form without any change in your created schemas, because it supports form declaration formats from these modules too. Here is an example:

    # And more formats to support schemas created for other similar modules
    # without changes:
    my_another_field:
      type: string
      label: My Another Field # Label from Drupal Core, priority: 4.
      title: My Another Field Title # Module: auto_config_form, priority: 3.
      description: My another field description # Module: auto_config_form, priority: 3.
      '#title': My Another Field Title # Module: schema_based_config_forms, priority: 2.
      '#description': My another field description # Module: schema_based_config_forms, priority: 2.
      '#field_prefix': <div>
      '#field_suffix': </div>
      '#schema_form_hide': true
      '#schema_form_plugin': my_custom_plugin
      third_party_settings:
        schema_form:
          element:
           '#title': My Another Field Title # The most relevant to this module, priority: 1.
           '#description': My another field description  # The most relevant to this module, priority: 1.

But if you use only this module to build forms, please stick to the recommended format described at the top.

Activity

Total releases
4
First release
Apr 2025
Latest release
6 months ago
Release cadence
38 days
Stability
0% stable

Release Timeline

Releases

Version Type Release date
1.0.0-alpha3 Pre-release Aug 16, 2025
1.0.0-alpha2 Pre-release May 12, 2025
1.0.0-alpha1 Pre-release May 1, 2025
1.0.x-dev Dev Apr 24, 2025