Question

I have this module for add newsletter subscription to checkout page in a Magento 2 project. I have added a checkbox field by following code:

app/code/MyNamespace/MyModule/Plugin/Checkout/Model/Checkout/LayoutProcessor.php

namespace Muaw\Subscription\Plugin\Checkout\Model\Checkout;


class LayoutProcessor
{
    /**
     * @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']['subscribe'] = [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                'customScope' => 'shippingAddress',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/checkbox',
                'options' => [],
                'id' => 'subscribe'
            ],
            'dataScope' => 'shippingAddress.subscribe',
            'label' => 'Opt-In to our news letter',
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => [],
            'sortOrder' => 250,
            'id' => 'subscribe',
            'value'=>'subscription'
        ];

        return $jsLayout;
    }
}

app/code/MyNamespace/MyModule/etc/frontend/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\Block\Checkout\LayoutProcessor">
            <plugin name="subscription" type="Muaw\Subscription\Plugin\Checkout\Model\Checkout\LayoutProcessor" sortOrder="100"/>
        </type>
    </config>

Rendered output:

Output

My problem is when I try to get the order data it does not added into post data

Post data:

Post data

Did I do anything wrong? Is there any other way to register this field and get post data? Help is appreciated.

Was it helpful?

Solution

You have to add the below files.

Vendor/Module/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-in-quote" type="Vendor\Module\Model\Checkout\ShippingInformationManagementPlugin" sortOrder="10"/>
    </type>
</config>

Vendor/Module/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="subscribe" type="string"/>
    </extension_attributes>
</config>

Vendor/Module/Model/Checkout/ShippingInformationManagementPlugin.php

<?php

namespace Vendor\Module\Model\Checkout;

class ShippingInformationManagementPlugin
{

    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();
        $subscribe = $extAttributes->getSubscribe();
        $quote = $this->quoteRepository->getActive($cartId);
        //$quote->setSubscribe($subscribe );
    }
}

Vendor/Module/view/frontend/requirejs-config.js

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

Vendor/Module/view/frontend/web/js/model/shipping-save-processor/default.js

copy and paste the Magento_Checkout/js/model/shipping-save-processor/default.js file above given path and modified payload method as given below.

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

                    }

                };

see my below pic it's came you can save it on quote table as given shippinginformationmanagementplufin.php file method.

enter image description here

feel free to ask if you have any queries.

OTHER TIPS

If you check the return type hint for \Magento\Checkout\Api\Data\ShippingInformationInterface::getExtensionAttributes() it explicitly states that the return value might be null. According to other examples in the core, the "right thing to do" seems to be to inject an ShippingInformationExtensionFactory.

Then use something like

$extAttributes = $addressInformation->getExtensionAttributes() ?: $this->extensionAttributesFactory->create();

I used Bojjaiah's solution but I had to change a few things to make it work with Magento 2.2.3.

default.js, change extension_attributes to:

extension_attributes: {
                        email: $('#customer-email').val(),
                        subscribe: Boolean($('[name="subscribe"]').attr('checked'))
                    }

In default.js you also need to add jQuery to the define or else you get an error on $.

If you happen to use Magento 2.2.3. delete the following line:

 payloadExtender(payload);

In the ShippingInformationManagementPlugin.php change the beforeSafeAddressInformation function to this:

    /**
 * @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();
    $email = $extAttributes->getEmail();
    $subscribe = $extAttributes->getSubscribe();

    if($subscribe === true){
        $subscriber = $this->subscriberFactory->create()->loadByEmail($email);
        if ($subscriber->getId() && $subscriber->getSubscriberStatus() == \Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED) {
        } else {
            $status = $this->subscriberFactory->create()->subscribe($email);
        }
    }
}

extension_attributes.xml, change this file to:

<?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="email" type="string" />
    <attribute code="subscribe" type="boolean" />
</extension_attributes>
</config>
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top