:::: MENU ::::

How to add custom form for a custom shipping method magento 2?

Recent QuestionsCategory: Magento 2 QuestionsHow to add custom form for a custom shipping method magento 2?
Mujahidh Haseem asked 2 months ago

i want to add a custom shipping method with some fields.
up to creating the custom shipping method completed.it will show in the checkout and saved the custom shipping method as the shipping in order.
I want to add some field after select this shipping method and save in the orders table.
How can i do this?

1 Answers
Best Answer
qaisarsatti Staff answered 2 months ago

hi Mujahidh Haseem,

Thanks for your question. I will try to answer you question first part.

create QaisarSatti/HelloWorld/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="testingfield" type="string"/>
    </extension_attributes>
</config>

create QaisarSatti/HelloWorld/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="custom_field" type="QaisarSatti\HelloWorld\Plugin\Checkout\Model\ShippingInformationManagement" sortOrder="1"/>
</type>
</config>

Create plugin QaisarSatti/HelloWorld/Plugin/Checkout/Model/ShippingInformationManagement.php

namespace QaisarSatti\HelloWorld\Plugin\Checkout\Model;
class ShippingInformationManagement
{
    protected $quoteRepository;
    public function __construct(
        \Magento\Quote\Model\QuoteRepository $quoteRepository
    ) {
        $this->quoteRepository = $quoteRepository;
    }
    /**
     * @param \Magento\Checkout\Model\ShippingInformationManagement $subject
     * @param $cartId
     * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
     */

    public function beforeSaveAddressInformation(
        \Magento\Checkout\Model\ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
    ) {
        $extAttributes = $addressInformation->getExtensionAttributes();
        $customfield = $extAttributes->getCustomfield();
        $quote->setCustomfield($customfield);
    }
}

Render the component shippingAdditional section.

QaisarSatti/HelloWorld/view/frontend/layout/checkout_index_index.xml

    <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="steps" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <item name="shipping-step" xsi:type="array">
                                            <item name="children" xsi:type="array">
                                                <item name="shippingAddress" xsi:type="array">
                                                    <item name="children" xsi:type="array">
                                                        <item name="shippingAdditional" xsi:type="array">
                                                            <item name="component" xsi:type="string">uiComponent</item>
                                                            <item name="displayArea" xsi:type="string">shippingAdditional</item>
                                                            <item name="children" xsi:type="array">
                                                                <item name="additional_block" xsi:type="array">
                                                                    <item name="component" xsi:type="string">QaisarSatti_HelloWOrld/js/view/checkout/shipping/additional-fields</item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
    </page>

Now create component.

QaisarSatti/HelloWorld/view/web/js/view/checkout/shipping/additional-fields.js

    define([
        'uiComponent'
   
    ], function (Component) {
        'use strict';
   
        return Component.extend({
            defaults: {
                template: 'QaisarSatti_HelloWorld/checkout/shipping/additional-fields'
            }    
        });
    });

Now create component html file.
QaisarSatti/HelloWorld/view/web/template/checkout/shipping/additional-fields.html

    <div >
        <div class="field">
            <label class="label" for="testingfield">
                <span data-bind="i18n: 'Test Field'"></span>
            </label>
            <div class="control">
                <input class="input-text" id="testingfield" name="testingfield" type="text" />
            </div>
        </div>
    </div>

Now overwrite following js

Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js

create QaisarSatti/HelloWorld/view/frontend/requirejs-config.js

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

Create default.js top add your field

QaisarSatti/HelloWorld/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());
                }

                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:{
                            testingfield: $('[name="testingfield"]').val()
                        }
                    }
                };

                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();
                    }
                );
            }
        };
    }
);

Create observer to get the data.

create QaisarSatti/HelloWorld/etc/events.xml

<?xml version="1.0" encoding="UTF-8"?>
<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="customfield" instance="QaisarSatti\HelloWorld\Observer\SaveCustomFieldObserver"/>
    </event>
</config>

create QaisarSatti/HelloWorld/Observer/SaveCustomFieldObserver.php

<?php
namespace QaisarSatti\HelloWorld\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
class SaveCustomFieldObserver implements ObserverInterface
{
    /**
     * @var \Magento\Framework\ObjectManagerInterface
     */

    protected $_objectManager;
    /**
     * @param \Magento\Framework\ObjectManagerInterface $objectmanager
     */

    public function __construct(\Magento\Framework\ObjectManagerInterface $objectmanager)
    {
        $this->_objectManager = $objectmanager;
    }
    public function execute(EventObserver $observer)
    {
        $order = $observer->getOrder();
        $quoteRepository = $this->_objectManager->create('Magento\Quote\Model\QuoteRepository');
        /** @var \Magento\Quote\Model\Quote $quote */
        $quote = $quoteRepository->get($order->getQuoteId());
        echo $quote->getCustomfield();
 
        return $this;
    }
}