1

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

12
  • Check with this module-github.com/EaDesgin/Magento2-City-Dropdown Commented Oct 17, 2019 at 8:28
  • actuallly Sir I tried that extension before as well but there were a lot of errors in that extension.
    – Asad Khan
    Commented Oct 17, 2019 at 11:06
  • Ok....Explain about the process...Do you want all the cities for all the region,countries? render cities automatically or manually (can add cities for region from admin panel)? Commented Oct 17, 2019 at 11:14
  • Yeah I want to add the cities of Pakistan... It'll be good that the cities is selected in admin panel else if it'll be fine to set the cities in code
    – Asad Khan
    Commented Oct 17, 2019 at 11:18
  • Ok, I will update the answer. Commented Oct 17, 2019 at 11:34

1 Answer 1

1

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);
        });
    };
});
30
  • Sir I didn't get Initialize custom component and [import][initialoptions] to get city array in city.js this point
    – Asad Khan
    Commented Oct 18, 2019 at 11:22
  • You can see the import array in initialOptions where i declared in layoutProcessor, This will set the city array in uiRegistry to get values in js file. city.js->options = city.initialOptions, Commented Oct 18, 2019 at 11:27
  • did I need to change something else except the vender name in that class??
    – Asad Khan
    Commented Oct 18, 2019 at 11:29
  • No....And Checkout is a module name..You can change as yours Commented Oct 18, 2019 at 11:39
  • yeah I know that... my module name is also checkout
    – Asad Khan
    Commented Oct 18, 2019 at 11:51

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.