horibles_problem
horibles_problem

Reputation: 31

Magento 2 add new field to shipping form

I'm trying to add a new field to the shipping address in Magento 2.3.4. I would like to add it "Magento way" that's why I used these tutorials:

https://devdocs.magento.com/guides/v2.3/howdoi/checkout/checkout_new_field.html https://www.edmondscommerce.co.uk/handbook/Platforms/Magento-2/Guides/Custom-Shipping-Address-Field/

The field appears correctly on the frontend, but after adding new address and filling that field and click "Ship here": enter image description here I got that error: enter image description here Here is my code:

1) At first, I thought that it is not necessary (this step is not in Magento 2 devdocs but appears in second tutorial) - app/code/Company/Module/Setup/Patch/Data/AddVipCodeAttribute.php:

<?php

namespace Company\Module\Setup\Patch\Data;

use Magento\Catalog\Model\Product;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchRevertableInterface;

class AddVipCodeAttribute implements DataPatchInterface, PatchRevertableInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

    /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * @var CustomerSetupFactory
     */
    private $customerSetupFactory;

    /**
     * Constructor
     *
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        EavSetupFactory $eavSetupFactory,
        CustomerSetupFactory $customerSetupFactory
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->eavSetupFactory = $eavSetupFactory;
        $this->customerSetupFactory = $customerSetupFactory;
    }

    /**
     * @inheritdoc
     */
    public function apply()
    {
        $this->moduleDataSetup->getConnection()->startSetup();
        /** @var CustomerSetup $customerSetup */
        $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $customerSetup->addAttribute('customer_address', 'vip_code', [
            'label' => 'Vip account code',
            'input' => 'text',
            'type' => Table::TYPE_TEXT,
            'source' => '',
            'required' => false,
            'position' => 333,
            'visible' => true,
            'system' => false,
            'is_used_in_grid' => false,
            'is_visible_in_grid' => false,
            'is_filterable_in_grid' => false,
            'is_searchable_in_grid' => false,
            'backend' => ''
        ]);
        $attribute = $customerSetup->getEavConfig()->getAttribute('customer_address', 'vip_code')
            ->addData(['used_in_forms' => [
                'adminhtml_customer_address',
                'adminhtml_customer',
                'customer_address_edit',
                'customer_register_address',
                'customer_address',
            ]]);
        $attribute->save();
        $this->moduleDataSetup->getConnection()->endSetup();
    }

    /**
     * @inheritDoc
     */
    public function revert()
    {
    }

    /**
     * @inheritdoc
     */
    public function getAliases()
    {
        return [];
    }

    /**
     * @inheritdoc
     */
    public static function getDependencies()
    {
        return [];
    }
}

2)I created a plugin class: etc/frontend/di.xml

<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="add_custom_field_checkout_form" type="Company\Module\Plugin\Checkout\LayoutProcessor" sortOrder="100"/>
    </type>
</config>

And layout processor app/code/Company/Module/Plugin/Checkout/LayoutProcessor.php

<?php

namespace Company\Module\Plugin\Checkout;

use Magento\Checkout\Block\Checkout\LayoutProcessor as LayoutProcessorCore;
use Magento\Customer\Model\Session;

class LayoutProcessor
{
    /**
     * @var Session
     */
    protected $session;

    public function __construct(
        Session $session
    ) {
        $this->session = $session;
    }

    /**
     * @param LayoutProcessorCore $subject
     * @param array $jsLayout
     *
     * @return array
     */
    public function afterProcess(
        LayoutProcessorCore $subject,
        array  $jsLayout
    ) {
            $customAttributeCode = 'vip_code';
            $customField = [
                'component' => 'Magento_Ui/js/form/element/abstract',
                'config' => [
                    // customScope is used to group elements within a single form (e.g. they can be validated separately)
                    'customScope' => 'shippingAddress.custom_attributes',
                    'customEntry' => null,
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'ui/form/element/input',
                    'tooltip' => [
                        'description' => 'Vip accounts code. Example: 123123123ASD',
                    ],
                ],
                'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode,
                'label' => 'Vip code',
                'provider' => 'checkoutProvider',
                'sortOrder' => 0,
                'validation' => [
                    'required-entry' => false
                ],
                'options' => [],
                'filterBy' => null,
                'customEntry' => null,
                'visible' => true,
            ];
            $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
                ['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $customField;

        return $jsLayout;
    }
}

3)JS files:

app/code/Company/Module/view/frontend/requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-shipping-information': {
                'Company_Module/js/add-new-field': true
            }
        }
    }
};

app/code/Company/Module/view/frontend/web/js/add-new-field.js

/*jshint browser:true jquery:true*/
/*global alert*/
define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote'
], function ($, wrapper, quote) {
    'use strict';

    return function (setShippingInformationAction) {

        return wrapper.wrap(setShippingInformationAction, function (originalAction) {
            var shippingAddress = quote.shippingAddress();
            if (shippingAddress['extension_attributes'] === undefined) {
                shippingAddress['extension_attributes'] = {};
            }

            shippingAddress['extension_attributes']['vip_code'] = shippingAddress.customAttributes['vip_code'];
            console.log(shippingAddress);
            // pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
            return originalAction();
        });
    };
});

[UPDATE] app/code/BartCompany/VipAccounts/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\Quote\Api\Data\AddressInterface">
        <attribute code="vip_code" type="string" />
    </extension_attributes>
</config>

Can anybody help me with that, I'm working on it almost a week, and tried a lot of solutions, but it is for me very important to do that by custom_attributes field. I will be grateful, thank You.

Upvotes: 1

Views: 2511

Answers (1)

horibles_problem
horibles_problem

Reputation: 31

I think i found the issue, here is a follow: https://github.com/magento/magento2/issues/26740

Upvotes: 1

Related Questions