ʍǝɥʇɐɯ
ʍǝɥʇɐɯ

Reputation: 4022

Magento: get region list for country in admin shipping module

Currently in my /etc/system.xml file I can use this to pull through a complete list of regions that are stored in Magento and display them as a multiselect. This works fine, however I would prefer to only pull through the regions for one country, e.g. the UK counties or US states:

                    <counties translate="label">
                        <label>Counties</label>
                        <frontend_type>multiselect</frontend_type>
                        <sort_order>10</sort_order>
                        <source_model>adminhtml/system_config_source_allregion</source_model>
                        <show_in_default>1</show_in_default>
                        <show_in_website>1</show_in_website>
                        <show_in_store>1</show_in_store>
                    </counties>

The reason for this is that I have added a lot of regions/states/counties on the system and it is now not a very user friendly multi-select box.

UPDATE:

After not immediately acting on the solutions provided below I revisited this problem some time later to put together my own solution inspired by the answers provided.

I copied app/code/core/Mage/Adminhtml/Model/System/Config/Source/Allregion.php to app/code/core/Mage/Adminhtml/Model/System/Config/Source/Ukregion.php

Then I changed the class definition to Mage_Adminhtml_Model_System_Config_Source_Ukregion.

Then I changed:

        $regionsCollection = Mage::getResourceModel('directory/region_collection')->load();

to include a country filter:

        $regionsCollection = Mage::getResourceModel('directory/region_collection')->addCountryFilter('GB')->load();

I now get the counties for the UK (which I had to edit myself but that is a different story-style-magento-problem).

Finally I changed my system.xml:

                    <counties translate="label">
                        <label>Counties</label>
                        <frontend_type>multiselect</frontend_type>
                        <sort_order>10</sort_order>
                        <source_model>adminhtml/system_config_source_ukregion</source_model>
                        <show_in_default>1</show_in_default>
                        <show_in_website>1</show_in_website>
                        <show_in_store>1</show_in_store>
                    </counties>

The use of 'UK' instead of 'GB' is entirely deliberate - GB does not include the NI counties it is just used for 'legacy reasons'. 'UK' does include Northern Ireland, as does my county list.

Upvotes: 3

Views: 11689

Answers (2)

clockworkgeek
clockworkgeek

Reputation: 37700

Take a look at the page System > Configuration > Shipping Settings, you can recreate how it's regions are adjusted to match the selected country.

Now look at the file app/code/core/Mage/Shipping/etc/system.xml. The country and region fields look like this:

<country_id translate="label">
    <label>Country</label>
    <frontend_type>select</frontend_type>
    <frontend_class>countries</frontend_class>
    <source_model>adminhtml/system_config_source_country</source_model>
    <sort_order>10</sort_order>
    <show_in_default>1</show_in_default>
    <show_in_website>1</show_in_website>
    <show_in_store>0</show_in_store>
</country_id>
<region_id translate="label">
    <label>Region/State</label>
    <frontend_type>text</frontend_type>
    <sort_order>20</sort_order>
    <show_in_default>1</show_in_default>
    <show_in_website>1</show_in_website>
    <show_in_store>0</show_in_store>
</region_id>

The important parts are:

  • The country has a class of countries and an ID of country_id.
  • The region has an ID of region_id.
  • The region is not a select and doesn't have a source model.

The javascript is already in place for config pages. It finds elements with a class of countries and uses it's ID to find a similarly named element (the region). When the first element changes the second is updated by AJAX.

When using this in the past I sometimes had trouble when there is more than one country/region pair on a page so it's best to avoid that situation.

Upvotes: 4

Italo Andr&#233;
Italo Andr&#233;

Reputation: 472

The source_model attribute defines the class "where" are the options of this multiselect field. You can create a new class with only the options you want to show in this field and point the source_model to this new class.

You should use the toOptionArray() method to define the options. A quick way of doing this is like the below example:

public function toOptionArray()
    {
        return array(
            array( 'value' => VALUE,
                'label' => LABEL ) ),

            array( 'value' => VALUE2,
                'label' => LABEL2 )
        );
    }

Of course, get the options from a database table would be a better practice.

Upvotes: 1

Related Questions