Ordering field blocks within a form

Because every field is actually a child block to a parent block of the form, you can simply use the XML layout to customize the way blocks are positioned relative to each other:

<move element="loki.checkout.shipping-step.shipping-address.street0" 
      destination="loki.checkout.shipping-step.address-form" 
      before="loki.checkout.shipping-step.shipping-address.street0"/>

But don't do this! This quickly becomes a hell to manage.

Using \Yireo\LokiCheckout\Util\Block\SortedChildBlocks instead

Because re-ordering fields is so common, a specific ViewModel \Yireo\LokiCheckout\Util\Block\SortedChildBlocks attempts to make things easier. First of all, it is instantiated somewhere in a PHTML template:

use Yireo\LokiCheckout\Util\Block\SortedChildBlocks;

/** @var SortedChildBlocks $sortedChildBlocks */
$sortedChildBlocks = $viewModelFactory->create(SortedChildBlocks::class);

Next, it is used to simply loop through the child blocks where needed:

<?php foreach ($sortedChildBlocks->getChildren($block) as $childBlock): ?>
    <?= $childBlock->toHtml() ?>
<?php endforeach; ?>

So far, nothing special. But the magic lies within its configuration via the XML layout.

Reordering fields the clever way

Within the XML layout, the parent block can be referenced to add a new argument sort_order:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:View/Layout:etc/page_configuration.xsd">
    <body>
        <referenceBlock name="loki.checkout.shipping-step.address-form">
            <arguments>
                <argument name="sort_order" xsi:type="array">
                    <item name="firstname" xsi:type="number">1</item>
                    <item name="lastname" xsi:type="number">2</item>
                    <item name="postcode" xsi:type="number">3</item>
                    <item name="street0" xsi:type="number">4</item>
                    ...
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

And as an alternative, you can also just write this down in plain text:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:View/Layout:etc/page_configuration.xsd">
    <body>
        <referenceBlock name="loki.checkout.shipping-step.address-form">
            <arguments>
                <argument name="sort_order" xsi:type="string">
                    firstname
                    lastname
                    postcode
                    street0
                    ...
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>
Last modified: January 22, 2025