Categories
CMS Magento Mastering Development

Checkout custom shipping address field – set as required

I have created a custom module that adds a text field in shipping address. It’s workin ok but I’d like to make it required. How can I do that?

I tried adding 'required-entry' => true at validation parameter, in file Plugin/Checkout/LayoutProcessor.php but it didn’t work.

Here are the module files:


Mymodules/FieldCheckout/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Mymodules_FieldCheckout',
    __DIR__
);

Mymodules/FieldCheckout/etc/frontend/di.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_model_service_quote_submit_before">
        <observer name="extra_shipping_cost" instance="Mymodules\FieldCheckout\Observer\SaveOrderObserver" />
    </event>
</config>

Mymodules/FieldCheckout/etc/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">
    <type name="Magento\Checkout\Model\ShippingInformationManagement">
        <plugin name="save_xorio_field_in_quote" type="Mymodules\FieldCheckout\Plugin\Checkout\Model\ShippingInformationManagement" sortOrder="1"/>
    </type>
</config>

Mymodules/FieldCheckout/etc/events.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_model_service_quote_submit_before">
        <observer name="extra_shipping_cost" instance="Mymodules\FieldCheckout\Observer\SaveOrderObserver" />
    </event>
</config>

Mymodules/FieldCheckout/etc/extension_attributes.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Checkout\Api\Data\ShippingInformationInterface">
        <attribute code="xorio_field" type="string" />
    </extension_attributes>
</config>

Mymodules/FieldCheckout/etc/module.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Mymodules_FieldCheckout" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

Mymodules/FieldCheckout/Observer/SaveOrderObserver.php

<?php
namespace Mymodules\FieldCheckout\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;

class SaveOrderObserver implements ObserverInterface
{
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $order = $observer->getEvent()->getOrder();
        $quote = $observer->getEvent()->getQuote();

        $order->setData('xorio_field', $quote->getXorioField());

        return $this;
    }
}

Mymodules/FieldCheckout/Plugin/Checkout/LayoutProcessor.php

<?php
namespace Mymodules\FieldCheckout\Plugin\Checkout\Block\Checkout;
class LayoutProcessor
{
    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']['xorio_field'] = [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                'customScope' => 'shippingAddress.custom_attributes',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/input',
                'options' => [],
                'id' => 'xorio-fields'
            ],
            'dataScope' => 'shippingAddress.custom_attributes.xorio_field',
            'label' => 'Town / Village',
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => [],
            'sortOrder' => 90,
            'id' => 'xorio-fields'
        ];


        return $jsLayout;
    }
}

Mymodules/FieldCheckout/Plugin/Checkout/Model/ShippingInformationManagement.php

<?php
namespace Mymodules\FieldCheckout\Plugin\Checkout\Model;


class ShippingInformationManagement
{
    protected $quoteRepository;

    protected $dataHelper;

    public function __construct(
        \Magento\Quote\Model\QuoteRepository $quoteRepository
    )
    {
        $this->quoteRepository = $quoteRepository;
    }

    public function beforeSaveAddressInformation(
        \Magento\Checkout\Model\ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
    )
    {
        if(!$extensionAttributes = $addressInformation->getExtensionAttributes())
        {
            return;
        }

        $quote = $this->quoteRepository->getActive($cartId);
        $quote->setXorioField($extensionAttributes->getXorioField());
    }
}

Mymodules/FieldCheckout/Setup/InstallSchema.php

<?php
namespace Mymodules\FieldCheckout\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;

class InstallSchema implements InstallSchemaInterface
{
    public function install(
        SchemaSetupInterface $setup, 
        ModuleContextInterface $context
    ){
        $setup->startSetup();

        $quote = $setup->getTable('quote');
        $salesOrder = $setup->getTable('sales_order');


        $setup->getConnection()->addColumn(
            $quote,
            'xorio_field',
            [
                'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                'nullable' => true,
                'comment' =>'Town / Village'
            ]
        );

        $setup->getConnection()->addColumn(
            $salesOrder,
            'xorio_field',
            [
                'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                'nullable' => true,
                'comment' =>'Town / Village'
            ]
        );

        $setup->endSetup();
    }
}

Mymodules/FieldCheckout/view/frontend/web/js/model/shipping-save-processor/default.js

define(
    [
        'jquery',
        'ko',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/resource-url-manager',
        'mage/storage',
        'Magento_Checkout/js/model/payment-service',
        'Magento_Checkout/js/model/payment/method-converter',
        'Magento_Checkout/js/model/error-processor',
        'Magento_Checkout/js/model/full-screen-loader',
        'Magento_Checkout/js/action/select-billing-address'
    ],
    function (
        $,
        ko,
        quote,
        resourceUrlManager,
        storage,
        paymentService,
        methodConverter,
        errorProcessor,
        fullScreenLoader,
        selectBillingAddressAction
    ) {
        'use strict';

        return {
            saveShippingInformation: function () {
                var payload;

                if (!quote.billingAddress()) {
                    selectBillingAddressAction(quote.shippingAddress());
                }

                var xorioField = $('[name="custom_attributes[xorio_field]"]').val();

                payload = {
                    addressInformation: {
                        shipping_address: quote.shippingAddress(),
                        billing_address: quote.billingAddress(),
                        shipping_method_code: quote.shippingMethod().method_code,
                        shipping_carrier_code: quote.shippingMethod().carrier_code,
                        extension_attributes:{
                            xorio_field: xorioField 

                        }
                    }
                };

                fullScreenLoader.startLoader();

                return storage.post(
                    resourceUrlManager.getUrlForSetShippingInformation(quote),
                    JSON.stringify(payload)
                ).done(
                    function (response) {
                        quote.setTotals(response.totals);
                        paymentService.setPaymentMethods(methodConverter(response.payment_methods));
                        fullScreenLoader.stopLoader();
                    }
                ).fail(
                    function (response) {
                        errorProcessor.process(response);
                        fullScreenLoader.stopLoader();
                    }
                );
            }
        };
    }
);

Mymodules/FieldCheckout/view/frontend/requirejs-config.js

var config = {
    "map": {
        "*": {
            'Magento_Checkout/js/model/shipping-save-processor/default': 'Mymodules_FieldCheckout/js/model/shipping-save-processor/default'
        }
    }
};

Leave a Reply

Your email address will not be published. Required fields are marked *