Skip to content

Form Modification Hooks

Hyvä Checkout form modification hooks let you customize forms at specific points in the form lifecycle. Each hook fires at a different stage, from initial construction through to final rendering, and provides different callback arguments. Understanding which hook to use is essential for making clean, targeted form customizations.

Modification Guidelines

Form modifications are intended for minor adjustments such as changing labels, adding CSS classes, inserting an individual field, or modifying field properties. Modification hooks are not designed for major overhauls like adding many fields at once.

For extensive changes, consider creating separate custom forms and conditionally rendering them based on context. For example, you could use tabs to switch between different form layouts.

How to choose the right modification hook

Finding the right modification hook (and modifier sort order) may not be straightforward.

Not every type of form and field manipulation is possible in every hook, so the desired effect determines which hook to use.

When more than one modifier alters the same field, both the modifier sortOrder and the hook execution order influence the order in which callbacks run. For example, a form:build modifier with a high sort order still executes before a form:build:magewire modifier with a lower sort order, because form:build fires first in the lifecycle.

Hook Lifecycle Order

The hooks fire in this order during the form lifecycle:

  1. form:init -- Form construction, add or remove fields
  2. form:populate -- After field population and built-in modifiers have been applied
  3. form:boot -- After initialization, all fields filled with data
  4. form:build -- Visual changes before rendering
  5. form:build:magewire -- Magewire-specific attributes before rendering
  6. form:updated -- When field values change (subsequent requests only)
  7. form:field:updated -- When a specific field value changes (subsequent requests only)
  8. form:action:edit -- When the "Edit Address" button is clicked
  9. form:action:create -- When the "New Address" button is clicked

form:init Hook

The form:init hook fires whenever a form is constructed. Use form:init to add or remove form fields, or to adjust the form itself along with its fields and values.

Callback Parameters Preceding Subsequent Since Associated hooks
1. EntityFormInterface $form Yes Yes 1.1.0 form:populate

form:populate Hook

The form:populate hook fires immediately after form:init, once all fields have been populated and all built-in modifiers have been applied. Use form:populate to make additional modifications to the form after the standard initialization is complete.

Callback Parameters Preceding Subsequent Since
1. EntityFormInterface $form Yes Yes 1.1.0

form:boot Hook

The form:boot hook fires after a form is fully constructed and all fields have been filled with their intended data. Use form:boot to alter field values right after initialization is complete.

Callback Parameters Preceding Subsequent Since Associated hooks
1. EntityFormInterface $form
2. MagewireAddressFormInterface $addressComponent
Yes Yes 1.1.2 form:[ADDRESS_NAMESPACE]:boot

form:build Hook

The form:build hook fires before the form is rendered. Use form:build to make visual-only changes such as adding extra CSS classes or styles to fields.

Visual changes only

The form:build hook is not intended for functional changes. Do not use form:build to add or remove fields. Use form:init for structural modifications instead.

Callback Parameters Preceding Subsequent Since
1. EntityFormInterface $form Yes Yes 1.1.0

form:build:magewire Hook

The form:build:magewire hook is an additional build-phase hook for Magewire-specific adjustments. Use form:build:magewire to add or modify Magewire attributes like wire:model or wire:target.

Magewire-driven forms only

Not all Hyvä Checkout forms are Magewire forms, although the address forms are. This hook only applies to Magewire-driven forms.

Internally, Hyvä Checkout uses the form:build:magewire hook to add all necessary Magewire attributes. Use this hook when you need to modify or remove a Magewire attribute that was added by core.

Callback Parameters Preceding Subsequent Since
1. EntityFormInterface $form Yes Yes 1.1.0

form:updated Hook

The form:updated hook fires when form field values change during subsequent (non-initial) requests. In addition to the generic form:updated hook, address-specific hooks form:shipping:updated and form:billing:updated are available.

Use form:updated to alter the value of fields based on the values of other fields.

Subsequent requests only

The form:updated hook does not fire on the initial page load. It only triggers during subsequent Magewire requests when field values change.

Callback Parameters Preceding Subsequent Since Associated hooks
1. EntityFormInterface $form
2. MagewireAddressFormInterface $addressComponent
No Yes 1.1.2 form:[ADDRESS_NAMESPACE]:updated

The following example shows how to use the form:billing:updated hook to auto-fill a street field based on the postcode value by calling an external API:

$form->registerModificationListener(
    'applyMyBillingModifications',
    'form:billing:updated',
    fn(EntityFormInterface $form, MagewireAddressFormInterface $addressComponent) => {
        // Get the current postcode field value.
        $postcodeValue = $form->getField('postcode')->getValue();

        // Call an external API to look up the street by postcode.
        $streetValue = $apiCall->getStreetByZipcode($postcodeValue);

        if ($streetValue) {
            $form->getField('street')->setValue($streetValue);
        }

        return $form;
    }
);

form:field:updated Hook

The form:field:updated hook fires when a specific field value is updated during subsequent requests. Use form:field:updated to transform or validate a single field's value at the moment it changes.

Subsequent requests only

Like form:updated, the form:field:updated hook only triggers during subsequent Magewire requests, not on the initial page load.

Callback Parameters Preceding Subsequent Since Associated hooks
1. EntityFormInterface $form
2. EntityFieldInterface $field
3. MagewireAddressFormInterface $addressComponent
No Yes 1.1.0 1. form:[FIELD_ID]:updated
2. form:[ADDRESS_NAMESPACE][FIELD_ID]:updated

The following example shows how to use the form:shipping:postcode:updated hook to capitalize the first letter of the postcode value whenever it changes:

$form->registerModificationListener(
    'applyMyShippingPostcodeModifications',
    'form:shipping:postcode:updated',
    fn(EntityFormInterface $form, EntityFieldInterface $field, MagewireAddressFormInterface $addressComponent) => {
        $field->setValue(ucfirst($field->getValue()));

        return $form;
    }
);

form:action:edit Hook

The form:action:edit hook fires when a visitor clicks the shipping or billing "Edit Address" button. Use form:action:edit to customize form behavior when an existing address is loaded for editing.

Callback Parameters Preceding Subsequent Since Associated hooks
1. EntityFormInterface $form
2. AddressInterface $address
No Yes 1.1.0 form:[FORM_NAMESPACE]:action:edit

form:action:create Hook

The form:action:create hook fires when a visitor clicks a shipping or billing "New Address" button. Use form:action:create to customize form behavior when a blank address form is opened.

Callback Parameters Preceding Subsequent Since Associated hooks
1. EntityFormInterface $form No Yes 1.1.0 form:[FORM_NAMESPACE]:action:create