Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Form Modifiers (Data/Meta Modifiers) for Dynamic Behavior

Form Modifiers (Data/Meta Modifiers) for Dynamic Behavior

~9 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026

So far, every field and every value has been declared directly in form.xml or the DataProvider. As soon as form behavior depends on conditions - computed default values, dynamically shown/hidden fields, derived labels - declarative XML alone isn't enough anymore. That's exactly what modifiers are for.

ModifierInterface and its two methods

A modifier implements \Magento\Ui\DataProvider\Modifier\ModifierInterface with exactly two methods: modifyData() changes the loaded values, modifyMeta() changes the structure/configuration (visibility, labels, required-field status) of the form fields.

app/code/Mironsoft/Announcement/Ui/DataProvider/Form/Modifier/DefaultTitle.php
<?php

declare(strict_types=1);

namespace Mironsoft\Announcement\Ui\DataProvider\Form\Modifier;

use Magento\Ui\DataProvider\Modifier\ModifierInterface;

/**
 * Fills in a placeholder title for newly created announcements.
 */
class DefaultTitle implements ModifierInterface
{
    /**
     * Sets a default title when no record has been loaded yet.
     *
     * @param array<string, mixed> $data Loaded form data, keyed by entity ID.
     * @return array<string, mixed>
     */
    public function modifyData(array $data): array
    {
        if (empty($data)) {
            $data['new'] = ['title' => __('New Announcement')->render()];
        }

        return $data;
    }

    /**
     * Leaves the field structure unchanged.
     *
     * @param array<string, mixed> $meta Current UI Component meta configuration.
     * @return array<string, mixed>
     */
    public function modifyMeta(array $meta): array
    {
        return $meta;
    }
}

Registering a modifier via di.xml

A modifier isn't referenced directly in form.xml - instead, it's hooked into the Modifier\Pool chain that the DataProvider uses internally, via a virtualType:

app/code/Mironsoft/Announcement/etc/adminhtml/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <virtualType name="Mironsoft\Announcement\Ui\DataProvider\Form\AnnouncementDataProvider"
                 type="Magento\Ui\DataProvider\ModifierPoolDataProvider">
        <arguments>
            <argument name="pool" xsi:type="object">AnnouncementFormModifierPool</argument>
        </arguments>
    </virtualType>

    <virtualType name="AnnouncementFormModifierPool" type="Magento\Ui\DataProvider\Modifier\Pool">
        <arguments>
            <argument name="modifiers" xsi:type="array">
                <item name="default_title" xsi:type="array">
                    <item name="class" xsi:type="string">Mironsoft\Announcement\Ui\DataProvider\Form\Modifier\DefaultTitle</item>
                    <item name="sortOrder" xsi:type="number">10</item>
                </item>
            </argument>
        </arguments>
    </virtualType>
</config>

Important: this doesn't extend the concrete DataProvider class from chapter 9 directly - instead, it's "overridden" via a same-named virtualType, which internally uses ModifierPoolDataProvider to swap the custom DataProvider class for a pool-capable variant.

Meta modification: hiding a field dynamically

modifyMeta() works with a nested array structure that exactly mirrors the XML tree from form.xml - fieldset/general/children/title/arguments/data/config, for example, corresponds to the <field name="title"> element inside the general fieldset:

public function modifyMeta(array $meta): array
{
    $meta['general']['children']['title']['arguments']['data']['config']['visible'] = false;

    return $meta;
}

Achtung: This direct array manipulation is error-prone - a misspelled key doesn't throw an error, it's simply ignored, and the field stays visible. Chapter 21 shows a cleaner, declarative approach via imports/exports for the most common cases of dependent fields.

Why modifiers - and not a ViewModel class

Modifiers are another example of chapter 1's honest disclaimer: the UI Components framework calls Modifier\Pool at a fixed point in the DataProvider's lifecycle and expects exactly ModifierInterface as the contract - an ArgumentInterface ViewModel can't be hooked in here. The injectable extra logic (for example a rule for when a field should be visible) still makes sense to extract into a separate service object that the modifier injects in its constructor - the modifier itself stays a thin adapter that way.