Magento 2 How to add validation to "street" in checkout address form?

Firstly, Magento's validation for checkout_index_index.xml is not working properly so, you have to insert the rules while you replace the street fields.

You can do this by creating a plugin and insert the fields in Layout AfterProcessor.

`namespace/module/etc/frontend/di.xml`
...
    <type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
        <plugin name="rewrite-street" type="Namespace\Module\Model\Checkout\LayoutProcessorPlugin" sortOrder="10"/>
    </type>
...

And the LayoutProcessorPlugin should look like this:

namespace/module/Model/Checkout/LayoutProcessorPlugin

...

<?php

namespace Namespace\Module\Model\Checkout;

class LayoutProcessorPlugin
{
/**
 * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
 * @param array $jsLayout
 * @return array
 */

public function afterProcess(
    \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
    array  $jsLayout
) {
    $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
            ['shippingAddress']['children']['shipping-address-fieldset']['children']['street'] = [
        'component' => 'Magento_Ui/js/form/components/group',
        'label' => __('Street Address'),
        'required' => true,
        'dataScope' => 'shippingAddress.street',
        'provider' => 'checkoutProvider',
        'sortOrder' => 60,
        'type' => 'group',
        'additionalClasses' => 'street',
        'children' => [
                [
                'component' => 'Magento_Ui/js/form/element/abstract',
                'config' => [
                    'customScope' => 'shippingAddress',
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'ui/form/element/input'
                ],
                'dataScope' => '0',
                'provider' => 'checkoutProvider',
                'validation' => ['required-entry' => true, "min_text_len‌​gth" => 1, "max_text_length" => 255],
            ],
                [
                'component' => 'Magento_Ui/js/form/element/abstract',
                'config' => [
                    'customScope' => 'shippingAddress',
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'ui/form/element/input'
                ],
                'dataScope' => '1',
                'provider' => 'checkoutProvider',
                'validation' => ['required-entry' => false, "min_text_len‌​gth" => 1, "max_text_length" => 255],
            ]
        ]
    ];
    return $jsLayout;
    }
}

You can insert in validation array any validation rule you want.


Creating a plugin and insert the fields in Layout AfterProcessor it is not the best way to solve that issue. The issue regarding the LayoutProcessorPlugin is first of all the layout xml (in this case the checkout_index_index.xml) is loaded afterward Magento is coping the all entries out of the attributes over the collected structure and in this case the LayoutProcessorPlugin is overriding the stuff.

So my Approach is to use the existing structure.

Here the (maybe cleaner) Approach This is a set up build in a Magento 2.2.8 Project

First of all, we need a mixin to validate the field.

Here is my mixin as an example based on the street field but it should be exactly the same for at least all of the address attributes:

Notice the JavaScript part is only necessary if you need a custom validation

define([
    'jquery',
    'jquery/validate'
], function ($) {
    "use strict";

    return function (validator) {
        validator.addRule(
            'validate-street-whitespace',
            function (value) {
                var pattern = /\s+\d+\s{0,}\w+$/;

                return value.match(pattern);
            },
            $.mage.__("Invalid street entry! Please add a whitespace between the street name and the house number!")
        );
        return validator;
    };
});

Here the setup for you're requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_Ui/js/lib/validation/validator': {
                'js/validation-mixin': true // pathing depends on you're file location
            }
        }
    }
};

This is Javascript wise the complete setup. Instead of the LayoutProcessorPlugin you need to update the validate_rules entry in you're attribute table in my case it was the customer_eav_attribute my entry look's like this

{"max_text_length":255, "min_text_length": 1, "validate-street-whitespace": true}

To roll this change out to all of your systems programmatically I set up a patch. Notice: This part is a bit custom from my current project but it should provide you're the Idea how to set it up

<?php
namespace YourProject\Config\Setup\UpgradeData;

use Magento\Eav\Setup\EavSetup;
use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Framework\Exception\LocalizedException;

class UpdateStreetAttribute0x0x72 extends EavSetup
{
    const STREET_ATTRIBUTE_CODE = 'street';

    /**
     * update street attribute
     * @throws LocalizedException
     */
    public function install()
    {
        $addressEntityTypeId = $this->getEntityTypeId(AddressMetadataInterface::ENTITY_TYPE_ADDRESS);
        $attributeData1 = $this->getAttribute($addressEntityTypeId, self::STREET_ATTRIBUTE_CODE);
        $attributeData1['validate_rules'] = '{"max_text_length":255, "min_text_length": 1, "validate-street-whitespace": true}';
        $this->updateAttribute($addressEntityTypeId, self::STREET_ATTRIBUTE_CODE, $attributeData1);

    }
}

Just as one more Notice adding a mixin for Magento_Ui/js/lib/validation/validator is only working in the Checkout.