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 ..
-
I think it is not possible. You can add validation to indicate a user only particular shipping country is allowed.– aravindCommented 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 ..– IlyasCommented Aug 1, 2019 at 8:54
2 Answers
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.
-
1Thanks Raj , it works perfectly for me with few changes. Commented Feb 4, 2022 at 17:43
-
1
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.