Magento – Use new field “Full Name” to replace “First Name” and “Last Name” in Checkout

checkoutfrontendknockoutjsmagento2

My idea is to use to add a new field called "Full Name" and it will fill out the "First Name" and the "Last Name" while you type in the checkout.
I have almost everything ready but I can't let know to "First Name" and "Last Name" that those values were updated.
Let show what I did and someone can tell me what I'm missing.

  1. Edit the frontend/di.xml

/app/code/CustomVendor/CustomModule/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="checkout_custom_fields" type="CustomVendor\CustomModule\Plugin\Checkout\Model\LayoutProcessor" sortOrder="1"/>
</type>
</config>

2.Add the LayoutProcessor.php
app/code/CustomVendor/CustomModule/Plugin/Checkout/Model/LayoutProcessor.php

    /**
 * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
 * @param array $jsLayout
 * @return array
 */
public function afterProcess(
    \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
    array  $jsLayout
) {
    $shippingConfiguration = &$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
    ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];

    $shippingConfiguration = $this->setFullName($shippingConfiguration);

    return $jsLayout;
}

    /**
 * Set "Full Name"
 * @param array $shippingConfiguration
 * @return array
 */
private function setFullName(array  $shippingConfiguration){

    $shippingConfiguration['full_name'] = [
        'component' => 'AdditionalProducts_AdditionalProductsModule/js/checkout/abstract',
        'config' => [
            'customScope' => 'shippingAddress',
            'template' => 'ui/form/field',
            'elementTmpl' => 'ui/form/element/input',
            'options' => [],
            'id' => 'full-name'
        ],
        'dataScope' => 'shippingAddress.full_name',
        'label' => __('Full Name'),
        'provider' => 'checkoutProvider',
        'visible' => true,
        'validation' => [
            'required-entry' => true
        ],
        'sortOrder' => 0,
        'id' => 'full-name',
    ];

    return $shippingConfiguration;
}
  1. Added abstract.js but with a custome code
    app/code/CustomVendor/CustomModule//view/frontend/web/js/checkout/abstract.js

    /**
     * Update whether value differs from default value
     */
    setDifferedFromDefault: function () {
        var value = typeof this.value() != 'undefined' && this.value() !== null ? this.value() : '',
            defaultValue = typeof this.default != 'undefined' && this.default !== null ? this.default : '';
    
        this.isDifferedFromDefault(value !== defaultValue);
    
        this.setFirstLastNameFromFullName(value);
    },
    
    /**
     * Extract from the 'Full Name' the 'First' and 'Last' Name
     *
     * @param value
     */
    setFirstLastNameFromFullName : function(value){
        var fullValue = value;
        var lastSpacePos = fullValue.lastIndexOf(" ");
        var nameLimit = 10;
        var lastNameLimit = 10;
    
        if (lastSpacePos > 0) { // Ignore values with no space character
            if(fullValue.substring(0, lastSpacePos).length < nameLimit){
                // Update "firstName"
                $($('[name="shippingAddress.firstname"]').find('input')[0]).val(fullValue.substring(0, lastSpacePos));
            }
            if(fullValue.substring(lastSpacePos + 1).length < lastNameLimit){
                // Update "lastName"
                $($('[name="shippingAddress.lastname"]').find('input')[0]).val(fullValue.substring(lastSpacePos + 1));
            }
        }else{
            if(fullValue.length < nameLimit){
                // Update "firstName"
                $($('[name="shippingAddress.firstname"]').find('input')[0]).val(fullValue);
                console.log(this.firstname);
            }
        }
    },
    

Best Answer

I found it!!! The solution was in this page.

I made two changes:

  1. Set "track" to FirstName and LastName in the LayoutProcessor.php.
  2. Update javascript function.

    1. LayoutProcessor.php

    
     /**

    • Set "Full Name"
    • @param array $shippingConfiguration
    • @return array */ private function setFullName(array $shippingConfiguration){

      $shippingConfiguration['full_name'] = [ 'component' => 'AdditionalProducts_AdditionalProductsModule/js/checkout/abstract', 'config' => [ 'customScope' => 'shippingAddress', 'template' => 'ui/form/field', 'elementTmpl' => 'ui/form/element/input', 'options' => [], 'id' => 'full-name' ], 'dataScope' => 'shippingAddress.full_name', 'label' => __('Full Name'), 'provider' => 'checkoutProvider', 'visible' => true, 'validation' => [ 'required-entry' => true, ], 'sortOrder' => 0, 'id' => 'full-name', ];

      $shippingConfiguration = $this->makeTrackableFirstLastName($shippingConfiguration);

      return $shippingConfiguration; }

    /**

    • Track firstName and lastName
    • @param array $shippingConfiguration
    • @return array */ private function makeTrackableFirstLastName(array $shippingConfiguration){ $shippingConfiguration['firstname']['tracks']['value'] = true; $shippingConfiguration['lastname']['tracks']['value'] = true;

      return $shippingConfiguration; }

  3. abstract.js

    
    define([
    'Magento_Ui/js/form/element/abstract',
    'mage/translate'
    ], function (AbstractField, $t) {
    'use strict';
    
    return AbstractField.extend({
        defaults: {
            modules: {
                firstname: '${ $.parentName }.firstname',
                lastname: '${ $.parentName }.lastname',
            }
        },
    
    
    hasChanged: function () {
        this._super();
        this.setFirstLastNameFromFullName();
    },
    
    /**
     * Extract from the 'Full Name' the 'First' and 'Last' Name
     */
    setFirstLastNameFromFullName : function(){
        var fullValue = this.value();
        var lastSpacePos = fullValue.lastIndexOf(" ");
        var nameLimit = 10;
        var lastNameLimit = 10;
    
        if (lastSpacePos > 0) { // Ignore values with no space character
            if(fullValue.substring(0, lastSpacePos).length < nameLimit){
                // Update "firstName"
                this.firstname().value(fullValue.substring(0, lastSpacePos));
            }
            if(fullValue.substring(lastSpacePos + 1).length < lastNameLimit){
                // Update "lastName"
                this.lastname().value(fullValue.substring(lastSpacePos + 1));
            }
        }else{
            if(fullValue.length < nameLimit){
                // Update "firstName"
                this.firstname().value(fullValue);
            }
        }
    },
    
    }); });

Related Topic