Magento – How to change the City Name to Drop Down on Checkout Page. Magento 2

checkoutdropdown-optionsfrontendmagento2

I want to change the city name to dropdown menu like in dropdown it shows specific cities name like NYC, Mumbai,HongKong,Karachi and etc how is it will be possible?
enter image description here

Best Answer

app/code/Vendor/Checkout/etc/frontend/di.xml

Override layoutProcessor block for customize city field and change arguments of onepage block for render city options.

<?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_layout"
                type="Vendor\Checkout\Plugin\LayoutProcessor" sortOrder="1"/>
    </type>
    <type name="Magento\Checkout\Block\Onepage">
        <arguments>
            <argument name="layoutProcessors" xsi:type="array">
                <item name="cityData" xsi:type="object">Vendor\Checkout\Block\Checkout\CityDataProcessor</item>
            </argument>
        </arguments>
    </type>
</config>

app/code/Vendor/Checkout/Plugin/LayoutProcessor.php

Initialize custom component and [import][initialoptions] to get city array in city.js

<?php

namespace Vendor\Checkout\Plugin;

class LayoutProcessor
{
    /**
     * @param LayoutProcessor $subject
     * @param array $result
     * @return array
     */
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        array $result
    ) {
        $result['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['city'] = $this->getConfig();

        unset($result['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['region_id']);

        unset($result['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['postcode']);

        $result['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['telephone']['validation']['max_text_length'] = '11';
        return $result;
    }

    /**
     * @return $field
     */
    private function getConfig()
    {
        $field = [
            'component' => 'Vendor_Checkout/js/city',
            'config' => [
                'customScope' => 'shippingAddress',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/select',
                'id' => 'city'
            ],
            'label' => 'City',
            'value' => '',
            'dataScope' => 'shippingAddress.city',
            'provider' => 'checkoutProvider',
            'sortOrder' => 80,
            'customEntry' => null,
            'visible' => true,
            'options' => [ ],
            'filterBy' => [
                'target' => '${ $.provider }:${ $.parentScope }.country_id',
                'field' => 'country_id'
            ],
            'validation' => [
                'required-entry' => true
            ],
            'id' => 'city',
            'imports' => [
                'initialOptions' => 'index = checkoutProvider:dictionaries.city',
                'setOptions' => 'index = checkoutProvider:dictionaries.city'
            ]
        ];


        return $field;
    }
}

app/code/Vendor/Checkout/Block/Checkout/CityDataProcessor.php

Add your city here, else better get cities from csv to avoid big array.

<?php
namespace Vendor\Checkout\Block\Checkout;

class CityDataProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface
{

    /**
     * Process js Layout of block
     *
     * @param array $jsLayout
     * @return array
     */
    public function process($jsLayout)
    {
        if (!isset($jsLayout['components']['checkoutProvider']['dictionaries']['city'])) {
            $jsLayout['components']['checkoutProvider']['dictionaries']['city'] = $this->getCityOptions();
        }

        return $jsLayout;
    }

    /**
     * Get country options list.
     *
     * @return array
     */
    private function getCityOptions()
    {
        //Add your city list here
        $options = [
            '1' => [
                'value'=>'city1',
                'name'=>'city1',
                'region_id'=>'1',//From database
            ],
            '2' => [
                'value'=>'city2',
                'name'=>'city2',
                'region_id'=>'2',//From databse
            ]
        ];

        if (count($options) > 0) {
            array_unshift(
                $options,
                ['title' => '', 'value' => '', 'label' => __('Please select a city.')]
            );
        }

        return $options;
    }
}

app/code/Vendor/Checkout/view/frontend/web/js/city.js

Render city options from initialoptions and filter with region_id

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

/**
 * @api
 */
define([
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Checkout/js/model/default-post-code-resolver',
    'jquery',
    'mage/utils/wrapper',
    'mage/template',
    'mage/validation',
    'underscore',
    'Magento_Ui/js/form/element/abstract',
    'jquery/ui'
], function (_, registry, Select, defaultPostCodeResolver, $) {
    'use strict';

    return Select.extend({
        defaults: {
            skipValidation: false,
            imports: {
                update: '${ $.parentName }.country_id:value'
            }
        },

        /**
         * @param {String} value
         */
        update: function (value) {
            var city = registry.get(this.parentName + '.' + 'city'),
                options = city.initialOptions,
                cityOptions = [];

            $.each(options, function (index, cityOptionValue) {
                //if(value == cityOptionValue.region_id){
                    var name = cityOptionValue.name;
                    var jsonObject = {
                        value: index,
                        title: name,
                        country_id: "",
                        label: name
                    };
                    cityOptions.push(jsonObject);
                //}
            });
            this.setOptions(cityOptions);
        }
    });
});

app/code/Vendor/Checkout/view/frontend/requirejs-config.js

/**
 * Copyright © 2018 EaDesign by Eco Active S.R.L. All rights reserved.
 * See LICENSE for license details.
 */

var config = {

    config: {
        mixins: {
            'Magento_Checkout/js/action/set-shipping-information': {
                'Vendor_Checkout/js/action/set-shipping-information-mixin': true
            }
        }
    }
};

app/code/Vendor/Checkout/view/frontend/web/js/action/set-shipping-information-mixin.js

Save city name instead of city value to database.

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

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

            var shippingAddress = quote.shippingAddress(),
                shippingCity = $("#shipping-new-address-form [name = 'city'] option:selected"),
                shippingCityValue = shippingCity.text();

            shippingAddress.city = shippingCityValue;

            return originalAction(container);
        });
    };
});
Related Topic