2

I have created a customer attribute which created dynamically from backend its fine works in customer_account_create and customer_account_edit and I stuck at saving customer attribute field data in after saving address information in the checkout form. After filling shipping address, shipping and press next button method I m getting the following error

message: "Internal Error. Details are available in Magento log file. Report ID: webapi-5d3aa1ebbf82a"

Exception log: 'Report ID: webapi-5d3aa1ebbf82a; Message: Property "TestAge" does not have corresponding setter in class "Magento\Quote\Api\Data\AddressExtensionInterface".' in D:\wamp64\www\m2\magento\vendor\magento\framework\Webapi\ErrorProcessor

and I followed this link

app/code/Cm/CustomerAttribute/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\Onepage">
        <arguments>
            <argument name="layoutProcessors" xsi:type="array">
                <item name="cm__fields_layoutprocessor" xsi:type="object">Cm\CustomerAttribute\Block\Checkout\LayoutProcessor</item>
            </argument>
        </arguments>
    </type>
</config>

app/code/ Cm/CustomerAttribute/Block/Checkout/LayoutProcessor.php

<?php
namespace Cm\CustomerAttribute\Block\Checkout;

class LayoutProcessor
{
    protected $customerSession;
    protected $resultPageFactory;
    public function __construct(\Cm\CustomerAttribute\Helper\Customerattribute $helper,
    \Magento\Customer\Api\CustomerRepositoryInterface $customerRepositoryInterface,
    \Magento\Customer\Model\Session $customerSession)
    {
        $this->helper = $helper;
        $this->customerRepositoryInterface = $customerRepositoryInterface;
        $this->customerSession = $customerSession;
    }
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        $jsLayout
    ) {
        $attributeCollection = $this->helper->getUserDefinedAttribures();

       if ($attributeCollection->getSize() > 0) 
       {
         foreach ($attributeCollection as $attribute)

         {
        if ($this->helper->isAttribureForCheckoutRegister($attribute->getAttributeCode()))
        {
        $frontEndLabel = $attribute->getStoreLabel($this->helper->getStoreId());

        $customAttributeCode = $attribute->getAttributeCode();
      if($this->customerSession->isLoggedIn()) {

        $customerId =$this->customerSession->getCustomer()->getId();
         $customer =$this->customerRepositoryInterface->getById($customerId);
        $customerAttr = $customer->getCustomAttribute($customAttributeCode)->getValue();
        }
        else
        {
          $customerAttr = NULL;
        }
        $fieldRequiredClass = ($attribute->getIsRequired()) ? 'true' : '' ;
        if($fieldRequiredClass == '')
        {
            $fieldRequiredClass = false;
        }
        $fieldFrontendClass = ($attribute->getFrontendClass()) ? $attribute->getFrontendClass() : '';
        $fieldInput =$attribute->getFrontendInput();
        $attributeId = $attribute->getAttributeId();
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();

        $attributeOptionAll = $objectManager->create(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class)
                                    ->setPositionOrder('asc')
                                    ->setAttributeFilter($attributeId)
                                    ->setStoreFilter()
                                    ->load();
        $opt_val = array();
        $allOptions=array();


        foreach ($attributeOptionAll->getData() as $key => $v) 
        {
          // $allid = $v['attribute_id'];
          $opt_val['value'] = $v['option_id'];
          $opt_val['label'] = $v['value'];
          $allOptions[] = $opt_val;
      }
        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
        ['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $this->addNewField($customAttributeCode,$frontEndLabel, $fieldRequiredClass,  $fieldFrontendClass,$fieldInput,  $allOptions, $customerAttr );

        }
      }
    }
    return $jsLayout;
    }

    private function addNewField($customAttributeCode, $frontEndLabel, $fieldRequiredClass,  $fieldFrontendClass, $fieldInput, $allOptions, $customerAttr  )
    {
        if($fieldInput == 'text')
        {
            $fieldInputType = 'input';
            $fieldAbstract =  'abstract';
        }
        elseif ($fieldInput == 'date') {
           $fieldInputType = 'date'; 
           $fieldAbstract =  'date';
        }
        elseif ($fieldInput == 'select') {
           $fieldInputType = 'select'; 
           $fieldAbstract =  'select';
        }

        elseif ($fieldInput == 'boolean') {
           $fieldInputType = 'select'; 
           $fieldAbstract =  'select';
           $allOptions = [
                 ['value' => '0', 'label' => 'No'],
                 ['value' => '1', 'label' => 'Yes']
               ];

        }
         elseif ($fieldInput == 'textarea') {
           $fieldInputType = 'textarea'; 
           $fieldAbstract =  'textarea';

        }
        $customField = [
            'component' => 'Magento_Ui/js/form/element/'.$fieldAbstract.'',
            'config' => [
                'customScope' => 'shippingAddress.custom_attributes',
                'customEntry' => null,
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/'.$fieldInputType.'',
                'rows' => 5
                // 'tooltip' => [
                //     'description' => 'this is what the field is for',
                // ],
            ],
            'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode,
            'label' => $frontEndLabel,
            'provider' => 'checkoutProvider',
            'sortOrder' => 1000,
            'validation' => [$fieldFrontendClass => true , 
                'required-entry' => $fieldRequiredClass],
            'options' =>  $allOptions,
            'filterBy' => null,
            'customEntry' => null,
            'visible' => true,
            'value' => $customerAttr
        ];

         return $customField;
    }
}

app/code/Cm/CustomerAttribute/view/frontend/requirejs-config.js

 var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-billing-address': {
                'Cm_CustomerAttribute/js/action/set-billing-address-mixin': true
            },
            'Magento_Checkout/js/action/set-shipping-information': {
                'Cm_CustomerAttribute/js/action/set-shipping-information-mixin': true
            },
            'Magento_Checkout/js/action/create-shipping-address': {
                'Cm_CustomerAttribute/js/action/create-shipping-address-mixin': true
            },
            'Magento_Checkout/js/action/place-order': {
                'Cm_CustomerAttribute/js/action/set-billing-address-mixin': true
            },
            'Magento_Checkout/js/action/create-billing-address': {
                'Cm_CustomerAttribute/js/action/set-billing-address-mixin': true
            }
        }
    }
};

app/code/Cm/CustomerAttribute/view/frontend/web/js/action/create-shipping-address-mixin.js

define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote'
], function ($, wrapper,quote) {
    'use strict';

    return function (setShippingInformationAction) {
        return wrapper.wrap(setShippingInformationAction, function (originalAction, messageContainer) {

            if (messageContainer.custom_attributes != undefined) {
                $.each(messageContainer.custom_attributes , function( key, value ) {
                    messageContainer['custom_attributes'][key] = {'attribute_code':key,'value':value};
                });
            }

            return originalAction(messageContainer);
        });
    };
});

app/code/Cm/CustomerAttribute/view/frontend/web/js/action/set-billing-address-mixin.js

define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote'
], function ($, wrapper,quote) {
    'use strict';

    return function (setBillingAddressAction) {
        return wrapper.wrap(setBillingAddressAction, function (originalAction, messageContainer) {

            var billingAddress = quote.billingAddress();

            if(billingAddress != undefined) {

                if (billingAddress['extension_attributes'] === undefined) {
                    billingAddress['extension_attributes'] = {};
                }

                if (billingAddress.customAttributes != undefined) {
                    $.each(billingAddress.customAttributes, function (key, value) {

                        if($.isPlainObject(value)){
                            value = value['value'];
                        }

                        billingAddress['extension_attributes'][key] = value;
                    });
                }

            }

            return originalAction(messageContainer);
        });
    };
});

app/code/Cm/CustomerAttribute/view/frontend/web/js/action/set-shipping-information-mixin.js

define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote'
], function ($, wrapper,quote) {
    'use strict';

    return function (setShippingInformationAction) {
        return wrapper.wrap(setShippingInformationAction, function (originalAction, messageContainer) {

            var shippingAddress = quote.shippingAddress();

            if (shippingAddress['extension_attributes'] === undefined) {
                shippingAddress['extension_attributes'] = {};
            }

            if (shippingAddress.customAttributes != undefined) {
                $.each(shippingAddress.customAttributes , function( key, value ) {

                    if($.isPlainObject(value)){
                        value = value['value'];
                    }

                    shippingAddress['customAttributes'][key] = value;
                    shippingAddress['extension_attributes'][key] = value;

                });
            }

            return originalAction(messageContainer);
        });
    };
});

app/code/Cm/CustomerAttribute/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="Cm_CustomerAttribute::ShippingInformationManagement" 
 type="Cm\CustomerAttribute\Plugin\Checkout\Model\ShippingInformationManagement" sortOrder="1"/>
          </type>
      </config>

app/code/Cm/CustomerAttribute/Plugin/Checkout/Model/ShippingInformationManagement.php

   <?php
    namespace Cm\CustomerAttribute\Plugin\Checkout\Model;

  class ShippingInformationManagement
{
    /**
     * @param \Magento\Checkout\Model\ShippingInformationManagement $subject
     * @param $cartId
     * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
     */
     protected $helper;
     protected $quoteRepository;
     public function __construct(

    \Bootsgrid\CustomerAttribute\Helper\Customerattribute $helper,
     \Magento\Quote\Model\QuoteRepository $quoteRepository
    ) {

        $this->helper = $helper;
         $this->quoteRepository = $quoteRepository;
    }


    public function beforeSaveAddressInformation(
        \Magento\Checkout\Model\ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
    ) {
       $extensionAttributes = $addressInformation->getShippingAddress();
       $custAttributes = $extensionAttributes->getExtensionAttributes();
       if($custAttributes )
       {
         $quote = $this->quoteRepository->getActive($cartId);


        $customField = $custAttributes->getTestTextarea();
        $cus = $custAttributes->getTestAge();
        $quote->setTestAge($cus);
        $quote->setTestTextarea($customField);



      }
        // error_log(print_r($custAttributes,1));
    }
}

How to save the customer_field dynamically in sales_order and quote order in magento 2

image:

enter image description here When using extension_attributes.xml file its saved into db but i want to pass a attribute_code dynamically in the xml file

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="test_age" type="string" /> \* how to pass "test_age" dynamically *\
        <attribute code="test_textarea" type="string" />
    </extension_attributes>
</config>

enter image description here

15
  • what a dynamic customer attributes?! you literlly posted us some code and a screenshot. how are we supposed to help Jul 12, 2019 at 11:55
  • @philipp Sander apologies for the improper post and i m update a post now. Please verify the above edited post Jul 12, 2019 at 12:15
  • what are "dynamic customer attributes" there is no such thing in magento Jul 12, 2019 at 12:17
  • What error have you faced? Jul 12, 2019 at 12:25
  • @philipp Sander i was created a custom attributes field dynamically from backend refer this extension i was try to done like a this extension Jul 12, 2019 at 12:47

4 Answers 4

1

Actually, the problem is when the page is loaded your custom field is not added means it is undefined and that is why that field value length is not getting. That is why it's occurred error.

Just you will and the condition in your js file. (when field length code is written.)

if (typeof [field] === "undefined") {
 // after your actually code
}

Let me know if you still facing the issue.

1

Seems like you've yet to add the mixin for saving data to the server. Have a look at Magento Devdocs - here

You are done with step 1. Start from Step 2 and you should be able to save your field. Let me know if you need any help.

5
  • i was done a step 2 also its not saved in the quote Jul 16, 2019 at 14:03
  • Please post your entire code. Did you create the mixin? What error are you getting?
    – coderGeek
    Jul 16, 2019 at 14:11
  • i was post my code. please check a edited question in above Jul 17, 2019 at 5:08
  • Are you getting something in the error logs from the plugin?
    – coderGeek
    Jul 17, 2019 at 13:26
  • Hello... what if this is a custom step? how can I save the data when Next button is pressed? I have not found any solution to this.
    – jstuardo
    Jul 28, 2021 at 22:39
1

You can check my question and answer seems like that.

Shipping address custom attribute value not display in address box in magento2.2.2

Shipping address custom attribute value not getting in RateRequest object in Carrier Model in magento2.x

please check all the answers. Let me know if you still issue.

0

You can refer this link of Magento DevDocs. You need to add mixin and define your attributes in extension_attributes.xml file so you can access and save your custom attribute's value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.