Magento – How to change City field to a dropdown in Checkout step Magento 2

magento2magento2.2

I tried multiple solutions found in here, but none seem to fit, the closest one was this one Magento 2 : How to change UI field(s) dynamically, here is my implementation of it:

My\Module\view\frontend\web\js\set-city-mixin.js

define([
'jquery',
'mage/utils/wrapper',
'mage/validation'], function ($, wrapper, validation) {
'use strict';
$(document).ready(function () {
    $(document).on('change', '[name="country_id"]', function() {
       //for country
       var region = $('select[name="region_id"]');
       changeCity(this, region);
    });

    $(document).on('change', '[name="region_id"]', function() {
       //for province or region
       var country = $('select[name="country_id"]');
       changeCity(country, this);
    });
});
function changeCity(country, region) {
    console.log("change city");
    var cityObject = $('[name="city"]');
    if ($(country).val() == 'CO') {
        console.log('Colombia');
        //send request with country and region and recieve json object
        var response = '[{"name": "Medellin", "code": "50011100"},{"name": "Cali", "code": "50011122"},{"name": "Bogota", "code": "50011133"}]';
        var cities = JSON.parse(response);
        if (cityObject.is('input')) {
            cityObject.replaceWith(function(){
                var select = $("<select>", {
                    html: $(this).html()
                });
                $.each(this.attributes, function(i, attribute){
                    select.attr(attribute.name, attribute.value);
                });
              return select;
            });
        } else {
            cityObject.empty();
        }

        if(cities != 'undefined' && cities.length > 0 ) {
            for( var i = 0; i < cities.length; i++ ) {
                cityObject.append("<option value="+cities[i].code+">"+cities[i]. name+"</option>");
            }
        }
    } else {
        if (cityObject.is('select')) {
            cityObject.replaceWith(function(){
                var select = $("<input>", {
                    html: $(this).html()
                });
                $.each(this.attributes, function(i, attribute){
                    select.attr(attribute.name, attribute.value);
                });
              return select;
            });
        }
    }
}

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

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

My\Module\view\frontend\requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-shipping-information': {
                'Tcc_Shipping/js/set-city-mixin': true
             }
        }
    }
};

The result is what I expected to be, but the validation for that field stops working:
Validation error

Any working alternative would be appreciated too, since what I need is to have a city dropdown with custom codes as values for them.

Best Answer

You can use this module, very useful https://github.com/EaDesgin/Magento2-City-Dropdown

i just had to change this view/frontend/web/js/form/element/city.js

line 38

romania = obj.RO,

for this obj.CO just that or if you want to put it dynamically

const countryCode = jQuery("select[name='country_id']").val();
romania = (obj[countryCode] !== undefined)? obj[countryCode] : obj.CO