3

How to limit the countries in the shipping address, for example, I want to allow all countries in billing address but only one in the shipping address( at the moment). Any idea how to achieve this in Magento 2.3.1 community ..

2
  • I think it is not possible. You can add validation to indicate a user only particular shipping country is allowed.
    – aravind
    Commented Jul 29, 2019 at 6:12
  • thanks aravind, but i am sure, there will be a way to do that .. where we can set billing and shipping countries from the back end ..
    – Ilyas
    Commented Aug 1, 2019 at 8:54

2 Answers 2

8

For show only one country in shipping address country dropdown we have to create plugin of LayoutProcessor method for override country_id children field of shipping-address-fieldset which we found in module-checkout/view/frontend/layout/checkout_index_index.xml file.

registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Trecks_Checkoutcountry',
    __DIR__
);

etc/module.xml:-

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Trecks_Checkoutcountry" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Checkout"/>
        </sequence>
    </module>
</config>

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="Treckslayoutprocessor" type="Trecks\Checkoutcountry\Plugin\LayoutProcessor"/>
    </type>
</config>

Plugin/LayoutProcessor.php:-

Here you can put different countries code in $countryIds of getCountryOptions() for show particular countries in dropdown.

<?php

namespace Trecks\Checkoutcountry\Plugin;
use Magento\Directory\Helper\Data as DirectoryHelper;

class LayoutProcessor
{

    protected $countryOptions;

    public function __construct(
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollection,
        DirectoryHelper $directoryHelper
    ) {
        $this->_storeManager = $storeManager;
        $this->countryCollectionFactory = $countryCollection;
        $this->directoryHelper = $directoryHelper;
    }

   
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        $result
    ) {

        $result['components']['checkout']['children']['steps']['children']['shipping-step']['children']
        ['shippingAddress']['children']['shipping-address-fieldset']['children']['country_id'] = [
            'component' => 'Magento_Ui/js/form/element/select',
            'config' => [
                'customScope' => 'shippingAddress',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/select',
                'id' => 'drop-down',
            ],
            'dataScope' => 'shippingAddress.country_id',
            'label' => 'Country',
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => [],
            'sortOrder' => 70,
            'id' => 'drop-down',
            'options' => $this->getCountryOptions()
        ];
        return $result;
    }

    public function getStoreId()
    {
        return $this->_storeManager->getStore()->getId();
    }

    //We have refernce this function from Magento\Checkout\Block\Checkout\DirectoryDataProcessor
    public function getCountryOptions()
    {
            $countryIds = array("US");
            //$countryIds = array("US","CA");
           
            $countryselection = $this->countryCollectionFactory->create()->loadByStore(
                $this->_storeManager->getStore()->getId());
            $countryselection->addFieldToFilter('country_id', ['in' => $countryIds]);
            $countryselection = $countryselection->toOptionArray();
            $countryarray = $this->orderCountryOptions($countryselection);

        return $countryarray;
    }


    public function orderCountryOptions(array $countryOptions)
    {
        $topCountryCodes = $this->directoryHelper->getTopCountryCodes();
        if (empty($topCountryCodes)) {
            return $countryOptions;
        }

        $headOptions = [];
        $tailOptions = [[
            'value' => 'delimiter',
            'label' => '──────────',
            'disabled' => true,
        ]];
        foreach ($countryOptions as $countryOption) {
            if (empty($countryOption['value']) || in_array($countryOption['value'], $topCountryCodes)) {
                $headOptions[] = $countryOption;
            } else {
                $tailOptions[] = $countryOption;
            }
        }
        return array_merge($headOptions, $tailOptions);
    }
}

Hope it works. Thanks.

2
  • 1
    Thanks Raj , it works perfectly for me with few changes. Commented Feb 4, 2022 at 17:43
  • 1
    Thanks Raj.. You saved my time
    – senthil
    Commented Nov 25, 2022 at 11:48
0

I don't believe this is currently possible to achieve through configuration in Magento 2.3, see this github issue for reference. It is possible to allow all countries for shipping and restrict the payment methods based on country, but not vice versa. A Magento extension would have to be implemented (or purchased) to achieve this behaviour. I am unsure of any 3rd party extensions that provide this.

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.