Categories: How ToMagento 2

How to Create Country & State Dropdown in Magento 2 Custom Frontend Form

Understanding that each business is different with unique requirements. Each store owner has his own needs for their web stores in order to provide better shopping experience. When a store is created for some specific countries or location and when admin needs to have some custom form, he needs to have it with selection options rather than text boxes in order to minimize users’ efforts to fill in and maximize their experience.While working on our client’s Magento 2 store, we required to have two selection boxes; one for countries and other for states selection. As the selection options are generally presented with dropdown, we choose to add 2 dropdowns to serve the purpose. To Create Country and State Dropdown in Magento 2 Custom Frontend Form, we implemented a custom code which I’m sharing with you today.

First create a file “index.php” at app\code\local\Vendor\Extension\Block with below code.

<?php
namespace Vendor\Extension\Block;
 
class Index extends \Magento\Framework\View\Element\Template
{
    protected $directoryBlock;
    protected $_isScopePrivate;
    
    public function __construct(
          \Magento\Framework\View\Element\Template\Context $context,
          \Magento\Directory\Block\Data $directoryBlock,
          array $data = []
         )
         {
          parent::__construct($context, $data);
          $this->_isScopePrivate = true;
          $this->directoryBlock = $directoryBlock;
         }
 
         public function getCountries()
         {
          $country = $this->directoryBlock->getCountryHtmlSelect();
          return $country;
         }
         public function getRegion()
         {
          $region = $this->directoryBlock->getRegionHtmlSelect();
          return $region;
         }
          public function getCountryAction()
         {
          return $this->getUrl('extension/extension/country', ['_secure' => true]);
         }
    
    
}

Now, you need to create another file at app\code\local\Vendor\Extension\view\frontend\layout\ with following code and rename it as “extension_extension_index.xml”

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
         <head>
          <title>extension</title>
         </head>
     <body>     
          <referenceContainer name="content">                  
                      <block class="Vendor\Extension\Block\Index" name="extension" template="extension/index.phtml">
                      </block>
          </referenceContainer>         
         </body>
</page>

Now create “index.phtml” with following code at app\code\local\Vendor\Extension\view\frontend\templates\extension

<?php
$countryList=$block->getCountries();
$regionList=$block->getRegion();  ?>
<form class="form retuns"
          action="<?php /* @escapeNotVerified */ echo $block->getFormAction(); ?>"
          id="return-form"
          method="post"
          data-hasrequired="<?php /* @escapeNotVerified */ echo __('* Required Fields') ?>"
          data-mage-init='{"validation":{}}'>
 
         <div class="field country required">
                        <label class="label" for="country"><span><?php /* @escapeNotVerified */ echo __('Country') ?></span></label>
                        <div class="control">
                                    <?php echo $countryList?>
                        </div>
               </div>
 
          <div class="field region required">
                       <label class="label" for="state"><span><?php /* @escapeNotVerified */ echo __('State') ?></span></label>
                       <div class="control">
                        <?php echo $regionList?>
                       </div>
                       </div>
                       
                       
                       <div class="field states required" style="display:none">
                       <label class="label" for="states"><span><?php /* @escapeNotVerified */ echo __('State') ?></span></label>
                       <div class="control">
                        <input name="state" id="states" title="<?php /* @escapeNotVerified */ echo __('State') ?>"  class="input-text" type="text" />
                       </div>
                       </div>
 
</form>
 
<script>
         jQuery(document).on('change','#country',function() {
          var param = 'country='+jQuery('#country').val();
          jQuery.ajax({
                      showLoader: true,
                      url: '<?php /* @escapeNotVerified */ echo $block->getCountryAction(); ?>',
                      data: param,
                      type: "GET",
                      dataType: 'json'
          }).done(function (data) {
                      jQuery('#state').empty();
                      if(data.value=='')
                      {
                                  jQuery('.field.states.required').show();
                                  jQuery('.field.region.required').hide();
                      }
                      else
                      {
                       jQuery('#state').append(data.value);
                                  jQuery('.field.states.required').hide();
                                  jQuery('.field.region.required').show();
                      }
          });
    });
</script>

Lastly, you need to create “Country.php” in your extension folder at app\code\local\Vendor\Extension\Controller\Extension\ with following code.

<?php
namespace Vendor\Extension\Controller\Extension;
 
class Country extends \Magento\Framework\App\Action\Action
{
         protected $resultJsonFactory;
    
    protected $regionColFactory;
 
         public function __construct(
          \Magento\Framework\App\Action\Context $context,
          \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
          \Magento\Directory\Model\RegionFactory $regionColFactory)
    {     
          $this->regionColFactory      = $regionColFactory;
          $this->resultJsonFactory      = $resultJsonFactory;
          parent::__construct($context);
         }
 
         public function execute()
         {
          $this->_view->loadLayout();
          $this->_view->getLayout()->initMessages();
          $this->_view->renderLayout();
 
          $result           = $this->resultJsonFactory->create();
          $regions=$this->regionColFactory->create()->getCollection()->addFieldToFilter('country_id',$this->getRequest()->getParam('country'));
         
          $html = '';
         
          if(count($regions) > 0)
          {
                      $html.='<option selected="selected" value="">Please select a region, state or province.</option>';
                      foreach($regions as $state)
                      {
                                  $html.=    '<option  value="'.$state->getName().'">'.$state->getName().'.</option>';
                      }
          }
          return $result->setData(['success' => true,'value'=>$html]);
   }
}

Adding country and state dropdowns in Magento 2 custom form is not rocket science, it’s as easy pie! Simply modify above code according to your custom fields and options, paste in your custom form and voila, you are done! I hope the code has enough served your purpose to implement country and state dropdown in Magento 2.
Let me know how did you customize the code and where have you used it. Also, tell me if you stuck somewhere and need help.

Don’t forget to flash out the 5 stars below if you like the tutorial.
Happy Coding!

Click to rate this post!
[Total: 26 Average: 4.5]
Dhiren Vasoya

Dhiren Vasoya is a Director and Co-founder at MageComp, Passionate 🎖️ Certified Magento Developer👨‍💻. He has more than 9 years of experience in Magento Development and completed 850+ projects to solve the most important E-commerce challenges. He is fond❤️ of coding and if he is not busy developing then you can find him at the cricket ground, hitting boundaries.🏏

View Comments

    • For the checkout page, you need to implement it differently, because checkout is created with the use of knockout js. We will see if we can write a blog for the same.

  • Hello, I am new to magento, integrate your code into a project, I am only adding the country

    I got an error:

    Undefined variable: countryList in .../Morwi/Registro/view/frontend/templates/registro.phtml on line 17

    --Saludos

    • You need to add this line in your phtml file.
      getCountries();
      $regionList=$block->getRegion(); ?>

      We have updated our blog too.

  • Hello, I am new to magento, integrate your code into a project, I am only adding the country

    I got an error:

    Undefined variable: countryList in .../Morwi/Registro/view/frontend/templates/registro.phtml on line 17

    --Saludos

    • Kindly check you have implemented the code properly and pass the proper field identification into your code for the country.

Recent Posts

Magento 2: How To Call JS on the Checkout Page?

Hello Magento mates, Today we will learn to add a call JS on the checkout…

3 days ago

Boost Your SEM Game: Unveiling the Top 10 Tools for Marketers in 2024

Business survival in today’s digital world has become extremely difficult. Using traditional marketing techniques is…

4 days ago

Five Essential Payroll Compliance Tips for eCommerce Startups

Are you setting up a payroll system for your eCommerce startup? Ensuring compliance with myriad…

5 days ago

Optimizing Laravel Blade: Unlocking Advanced Fetcher Techniques

In the expansive universe of Laravel development, Blade serves as the stellar templating engine, propelling…

5 days ago

Magento 2: Add Quantity Increment and Decrement on Category Page

Hello Magento Friends, In this blog, we will discuss about adding quantity increment and decrement…

7 days ago

How to Integrate ChatGPT with Laravel Application?

In this guide, we'll explore how to integrate ChatGPT, an AI-powered chatbot, with a Laravel…

1 week ago