Question

I need to add country and state drop down in admin form how to do it

Was it helpful?

Solution

in admin form block in _prepareForm() add country and region

that is

in __construct() add country config source

protected $_countryFactory;

    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Data\FormFactory $formFactory
     * @param \Magento\Store\Model\System\Store $systemStore
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Store\Model\System\Store $systemStore,
        \Magento\Cms\Model\Wysiwyg\Config $wysiwygConfig,
        \Magento\Directory\Model\Config\Source\Country $countryFactory,
        \Sugarcode\Test\Model\Status $status,
        array $data = []
    ) {
        $this->_systemStore = $systemStore;
        $this->_wysiwygConfig = $wysiwygConfig;
        $this->_status = $status;
        $this->_countryFactory = $countryFactory;
        parent::__construct($context, $registry, $formFactory, $data);
    }

and in _prepareForm()

     protected function _prepareForm()
        {
    .
    .
    .
    .
    .
    old field 
    .
    .
    .
    .
    $optionsc=$this->_countryFactory->toOptionArray();
            $country = $fieldset->addField(
                'country_id',
                'select',
                [
                    'name' => 'country_id',
                    'label' => __('Country'),
                    'title' => __('Country'),
               // 'onchange' => 'getstate(this)',
                    'values' => $optionsc,
                ]
            );
            //$optionsc=$this->_countryFactory->toOptionArray();
            $fieldset->addField(
                'region_id',
                'select',
                [
                    'name' => 'region_id',
                    'label' => __('Region'),
                    'title' => __('Region'),
                    'values' =>  ['--Please Select Country--'],
                ]
            );


         /*
            * Add Ajax to the Country select box html output
            */
      $country->setAfterElementHtml("   
            <script type=\"text/javascript\">
                    require([
                    'jquery',
                    'mage/template',
                    'jquery/ui',
                    'mage/translate'
                ],
                function($, mageTemplate) {
                   $('#edit_form').on('change', '#country_id', function(event){
                        $.ajax({
                               url : '". $this->getUrl('test/*/regionlist') . "country/' +  $('#country_id').val(),
                                type: 'get',
                                dataType: 'json',
                               showLoader:true,
                               success: function(data){
                                    $('#region_id').empty();
                                    $('#region_id').append(data.htmlconent);
                               }
                            });
                   })
                }

            );
            </script>"
        );
$form->setValues($model->getData());
        $this->setForm($form);

        return parent::_prepareForm();
    }

and create admin side action file to get region that is app\code\Sugarcode\Test\Controller\Adminhtml\Lists\Regionlist.php

<?php
/**
 *
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

// @codingStandardsIgnoreFile

namespace Sugarcode\Test\Controller\Adminhtml\Lists;

/**
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Regionlist extends \Magento\Framework\App\Action\Action
{
            /**
         * @var \Magento\Framework\View\Result\PageFactory
         */
        protected $resultPageFactory;
    /**
     * @var \Magento\Directory\Model\CountryFactory
     */
    protected $_countryFactory;

        /**
         * @param \Magento\Framework\App\Action\Context $context
         * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
         */
        public function __construct(
            \Magento\Framework\App\Action\Context $context,
            \Magento\Directory\Model\CountryFactory $countryFactory,
            \Magento\Framework\View\Result\PageFactory $resultPageFactory
        )
        {
            $this->_countryFactory = $countryFactory;
            $this->resultPageFactory = $resultPageFactory;
            parent::__construct($context);
        }
    /**
     * Default customer account page
     *
     * @return void
     */
    public function execute()
    {


        $countrycode = $this->getRequest()->getParam('country');
        $state = "<option value=''>--Please Select--</option>";
        if ($countrycode != '') {
            $statearray =$this->_countryFactory->create()->setId(
                    $countrycode
                )->getLoadedRegionCollection()->toOptionArray();
            foreach ($statearray as $_state) {
                if($_state['value']){
                    $state .= "<option >" . $_state['label'] . "</option>";
            }
           }
        }
       $result['htmlconent']=$state;
         $this->getResponse()->representJson(
            $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode($result)
        );
    } 

  }

once you change country region will load same way you can do for city also

If any one know better then this solution as like in we use in edit.phtml please share us

OTHER TIPS

In the block constructor, you'll need to enable two classes with the collection of regions and countries. Also, don't forget to add the corresponding fields in there.

Next, apply the standard RegionUpdater from lib/web/varien/form.js. it can be added in any convenient for you way - in our example we're using a child block with the template where it is called (just note that there're some required parameters: country elements, region (text), region (select) and the object that contains data for countries and regions (from the Helper directory).

In case you need to modify the list of countries and regions, do that not only in the form , but also in the data object from RegionUpdater.

Changes in the class of the form block, add new classes to di, the __construct method and make changes to the _prepareForm method.

<?php
/**
 * @var \Magento\Directory\Model\Config\Source\Country
 */
protected $_country;

/**
 * @var \Magento\Directory\Model\RegionFactory
 */
protected $_regionFactory;

// ... add them in __construct

// ...

// Add next changes in the _prepareForm method

$countries = $this->_country->toOptionArray(false, 'US');
$regionCollection = $this->_regionFactory->create()->getCollection()->addCountryFilter(
    $formData['country_id']
);
$regions = $regionCollection->toOptionArray();

$fieldset->addField(
    'country_id',
    'select',
    ['name' => 'country_id', 'label' => __('Country'), 'required' => true, 'values' => $countries]
);

$fieldset->addField(
    'region_id',
    'select',
    ['name' => 'region_id', 'label' => __('State'), 'values' => $regions]
);

$fieldset->addField(
    'region',
    'text',
    ['name' => 'region', 'label' => __('Region')]
);

$fieldset->addField(
    'city',
    'text',
    ['name' => 'city', 'label' => __('City')]
);

$this->setChild(
    'form_after',
    $this->getLayout()->createBlock('Magento\Framework\View\Element\Template')->setTemplate('Vendor_Module::js.phtml')
);
?>

> Vendor_Module::js.phtml

<script>
    require([
        "jquery",
        "mage/adminhtml/form"
    ], function ($) {

        var updater = new RegionUpdater($('[name=country_id]')[0], $('[name=region]')[0], $('[name=region_id]')[0],
            <?php echo $this->helper('Magento\Directory\Helper\Data')->getRegionJson() ?>,
            'hide'
        );
        updater.disableRegionValidation();
        window.updater = updater;
    });
</script>

This is how it works:

1) by default

enter image description here

2) After you select the USD, the text field for the region is hidden (the 5th argument RegionUpdater constructor - this method will be applied to any inactive fields, also it can be hidden or disabled)

enter image description here

3) For Albania, there're no regions by default. Hence, we can see just the text field with hidden regions:

enter image description here

4) For Switzerland, we can see the regions again:

enter image description here

And it it goes without saying that you should make it convenient to use for your clients, as using the Hide method, the filed label is NOT hidden.

But upon the whole, RegionUpdater works well for a non-UI forms of Magento.

P.S. Also note that there's no way to add an updater for cities,as by default, Magento doesn't support the lists of Cities.

You can try using/replicationg the Config module's way.

Add the js.phtml block, that's also used in the shipping origin config, to your layout xml.

    <referenceContainer name="js">
        <block class="Magento\Backend\Block\Template" template="Magento_Config::system/config/js.phtml"/>
    </referenceContainer>

Name your field ids as "country_id" and "region_id" and add "countries" css class to the country_id field.

$fieldset->addField(
    'country_id',
    'select',
    [
        'name'  => 'country_id',
        'label' => __('Country'),
        'title' => __('Country'),
        'values' => array_merge(['' => ''], $this->_countryOptions->toOptionArray()),
        'class' => 'countries',
    ]
);
$fieldset->addField(
    'region_id',
    'text',
    [
        'name'  => 'region_id',
        'label' => __('Region/State'),
        'title' => __('Region/State'),
    ]
);
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top