country-data-filter
v1.3.0
Published
Geographical data for 190 countries — provinces, districts, cities and postal codes. Includes React (Ant Design / MUI) and Angular (PrimeNG) location picker cascade components with full TypeScript support.
Downloads
284
Maintainers
Keywords
Readme
country-data-filter
A comprehensive npm package providing detailed geographical data for 190 countries — including provinces, districts, cities, postal codes, currency codes, and phone country codes. Ideal for address forms, location pickers, and any application that needs structured geographical information.
Installation
npm install country-data-filterData Coverage
- 190 countries with province/state, district, and city data
- Postal codes where available (from GeoNames dataset)
- Currency code and international dialling code per country
- Localized admin labels (e.g.
provinceLabel: "State",districtLabel: "County")
Data Structure
Country
└─ provinces
└─ Province
└─ districts
└─ District
└─ cities[]
└─ { name, postalCode, type }Usage
JavaScript (CommonJS)
const {
getCountries,
getDataByCountry,
getDataByProvince,
getDataByDistrict,
getDataByCity,
getDataByCountryProvince,
getDataByCountryProvinceDistrict,
getDataByCountryProvinceDistrictCity,
getDataByEtherCountryProvinceDistrictCity,
getDataByCountryDistrict,
getDataByCountryCity,
getDataByProvinceDistrict,
getDataByProvinceCity,
getDataByDistrictCity,
getCurrencyByCountry,
getDataByPostalCode,
getCitiesWithPostalCodesByCountry,
listFunctions,
} = require("country-data-filter");TypeScript / ESM
import {
getCountries,
getDataByCountry,
getDataByProvince,
getDataByDistrict,
// ... etc
} from "country-data-filter";Functions
getCountries()
Returns an array of all supported countries with metadata.
const countries = getCountries();
// [{ name, code, currency, countryCode, provinceLabel, districtLabel }, ...]getDataByCountry(countryCode)
Returns all provinces, districts, and cities for a country.
const result = getDataByCountry("LK");
// { provinces: [...], districts: [...], cities: [...] }| Parameter | Type | Description |
|-----------|------|-------------|
| countryCode | string | ISO 3166-1 alpha-2 code (e.g. "US", "LK", "NG") |
getDataByProvince(provinceName)
Returns districts and cities for a matching province name (searches all countries).
const result = getDataByProvince("Western Province");getDataByDistrict(districtName)
Returns the country, province, and cities for a matching district name.
const result = getDataByDistrict("Colombo");getDataByCity(cityName)
Returns the country, province, and district for a matching city name.
const result = getDataByCity("Kandy");getDataByCountryProvince(countryCode, provinceName)
Returns districts and cities for a specific province within a country.
const result = getDataByCountryProvince("LK", "Western Province");getDataByCountryProvinceDistrict(countryCode, provinceName, districtName)
Returns cities for a specific district within a province and country.
const result = getDataByCountryProvinceDistrict("LK", "Western Province", "Colombo");getDataByCountryProvinceDistrictCity(countryCode, provinceName, districtName, cityName)
Returns data for a specific city at the full hierarchy level.
const result = getDataByCountryProvinceDistrictCity("LK", "Western Province", "Colombo", "Colombo");getDataByEtherCountryProvinceDistrictCity(countryCode?, provinceName?, districtName?, cityName?)
Flexible search — pass any combination of parameters (use null to skip a level). Returns all matching records.
// Find all districts named "Central" across all countries
const result = getDataByEtherCountryProvinceDistrictCity(null, null, "Central", null);
// Find all cities named "Springfield" in the US
const result = getDataByEtherCountryProvinceDistrictCity("US", null, null, "Springfield");getDataByCountryDistrict(countryCode, districtName)
Returns cities for a district within a specific country.
const result = getDataByCountryDistrict("GB", "Greater London");getDataByCountryCity(countryCode, cityName)
Returns province and district data for a city within a specific country.
const result = getDataByCountryCity("AU", "Sydney");getDataByProvinceDistrict(provinceName, districtName)
Returns cities for a district within a named province (across all countries).
const result = getDataByProvinceDistrict("Ashanti Region", "Kumasi");getDataByProvinceCity(provinceName, cityName)
Returns district data for a city within a named province.
const result = getDataByProvinceCity("Koshi Province", "Biratnagar");getDataByDistrictCity(districtName, cityName)
Returns country and province data for a city within a named district.
const result = getDataByDistrictCity("Mombasa", "Mombasa");getCurrencyByCountry(countryCode)
Returns the currency code for a country.
const currency = getCurrencyByCountry("JP");
// { currency: "JPY" }getDataByPostalCode(postalCode)
Returns location data matching a postal code (countries with GeoNames postal data).
const result = getDataByPostalCode("10001");
// { country, province, district, city }getCitiesWithPostalCodesByCountry(countryCode)
Returns all cities with postal codes for a given country.
const cities = getCitiesWithPostalCodesByCountry("US");listFunctions()
Returns an object containing all available functions — useful for runtime introspection.
const fns = listFunctions();React Location Picker
A headless, UI-library-agnostic cascade picker for country → province → district → city. You supply the dropdown component; the hook/component handles all data loading and cascade resets.
Peer dependencies
# Core (required)
npm install react react-dom
# Ant Design adapter (optional)
npm install antd
# MUI adapter (optional)
npm install @mui/material @emotion/react @emotion/styledQuick start — Ant Design
import { AntdLocationPicker } from 'country-data-filter/react/antd';
function AddressForm() {
return (
<AntdLocationPicker
onCountryChange={(code) => console.log('country code:', code)}
onCountrySelect={(country) => console.log('full object:', country)}
onProvinceChange={(name) => console.log('province:', name)}
onDistrictChange={(name) => console.log('district:', name)}
onCityChange={(name) => console.log('city name:', name)}
onCitySelect={(city) => console.log('city + postal:', city)}
/>
);
}Quick start — MUI
import { MuiLocationPicker } from 'country-data-filter/react/mui';
<MuiLocationPicker
onCountryChange={(code) => setCountry(code)}
onProvinceChange={(name) => setProvince(name)}
onCityChange={(name) => setCity(name)}
onCitySelect={(city) => setPostalCode(city?.postalCode ?? '')}
/>Quick start — any UI library (renderSelect)
import { LocationPicker } from 'country-data-filter/react';
<LocationPicker
onCountryChange={setCountry}
onProvinceChange={setProvince}
renderSelect={({ id, value, options, onChange, placeholder }) => (
<MySelect
key={id}
value={value}
options={options}
placeholder={placeholder}
onChange={onChange}
/>
)}
/>Headless hook
Use useLocationPicker when you need full control over rendering:
import { useLocationPicker } from 'country-data-filter/react';
function MyPicker() {
const {
country, province, district, city,
countryOptions, provinceOptions, districtOptions, cityOptions,
setCountry, setProvince, setDistrict, setCity,
showProvince, showDistrict, showCity,
provinceLabel, districtLabel,
} = useLocationPicker({
onCountryChange: (v) => console.log(v),
onProvinceChange: (v) => console.log(v),
onDistrictChange: (v) => console.log(v),
onCityChange: (v) => console.log(v),
});
return (
<div>
<select value={country ?? ''} onChange={e => setCountry(e.target.value || null)}>
{countryOptions.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
</select>
{showProvince && (
<select value={province ?? ''} onChange={e => setProvince(e.target.value || null)}>
{provinceOptions.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
</select>
)}
</div>
);
}Controlled mode
Pass *Value props to take control of each level:
const [country, setCountry] = useState<string | null>(null);
const [city, setCity] = useState<string | null>(null);
<LocationPicker
countryValue={country}
cityValue={city}
onCountryChange={setCountry}
onCityChange={setCity}
renderSelect={...}
/>Dual callbacks — value vs full object
Every level fires two callbacks: one with the form value, one with the full raw object:
| Callback | Receives | Use for |
|---|---|---|
| onCountryChange(value) | Mapped option value (e.g. "LK") | Form state, storing the code |
| onCountrySelect(country) | Full CountryRaw object | Reading name, currency, dialling code |
| onCityChange(value) | City name string | Form state |
| onCitySelect(city) | Full CityRaw object | Reading postalCode, type |
<LocationPicker
onCountryChange={(code) => form.setFieldValue('country', code)}
onCountrySelect={(c) => setDialCode(c?.countryCode ?? '')}
onCityChange={(name) => form.setFieldValue('city', name)}
onCitySelect={(city) => form.setFieldValue('postalCode', city?.postalCode ?? '')}
renderSelect={...}
/>Custom option values
Control what value onChange receives without writing a full mapper:
// onChange receives dialling code ("+94") instead of country code ("LK")
<LocationPicker countryValueKey="countryCode" onCountryChange={setDialCode} renderSelect={...} />
// dropdown labels show currency symbols
<LocationPicker countryLabelKey="currency" onCountryChange={setCode} renderSelect={...} />Custom mappers (advanced)
<LocationPicker
// Combine fields in the label
countryMapper={(c) => ({ label: `${c.name} (${c.countryCode})`, value: c.code })}
// Show postal code next to city name
cityMapper={(c) => ({ label: c.postalCode ? `${c.name} — ${c.postalCode}` : c.name, value: c.name })}
renderSelect={...}
/>Which dropdowns appear
The dropdowns shown are determined by which on*Change callbacks are provided:
| Props provided | Dropdowns shown |
|---|---|
| onCountryChange only | Country |
| onCountryChange + onProvinceChange | Country → Province |
| + onDistrictChange | Country → Province → District |
| + onCityChange | Country → Province → District → City |
Props reference
| Prop | Type | Default | Description |
|---|---|---|---|
| onCountryChange | (value: string \| null) => void | — | Fires on country select; presence shows the country dropdown |
| onCountrySelect | (country: CountryRaw \| null) => void | — | Fires with full country object on each change |
| onProvinceChange | (value: string \| null) => void | — | Fires on province select; presence shows province dropdown |
| onDistrictChange | (value: string \| null) => void | — | Fires on district select; presence shows district dropdown |
| onCityChange | (value: string \| null) => void | — | Fires on city select; presence shows city dropdown |
| onCitySelect | (city: CityRaw \| null) => void | — | Fires with full city object (includes postalCode, type) |
| countryValue | string \| null | — | Controlled country value |
| provinceValue | string \| null | — | Controlled province value |
| districtValue | string \| null | — | Controlled district value |
| cityValue | string \| null | — | Controlled city value |
| countryLabelKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'name' | Field to use as option label |
| countryValueKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'code' | Field to use as option value |
| countryMapper | (c: CountryRaw) => LocationOption | — | Full custom mapper (overrides countryLabelKey/countryValueKey) |
| provinceMapper | (name: string) => LocationOption | — | Custom province option mapper |
| districtMapper | (name: string) => LocationOption | — | Custom district option mapper |
| cityMapper | (city: CityRaw) => LocationOption | — | Custom city option mapper |
| renderSelect | (props: RenderSelectProps) => ReactNode | required | Your dropdown renderer |
| layout | 'vertical' \| 'horizontal' | 'vertical' | Flex direction of the wrapper |
| className | string | — | Class added to the wrapper <div> |
| style | CSSProperties | — | Inline styles for the wrapper <div> |
AntdLocationPicker additional props
| Prop | Type | Description |
|---|---|---|
| selectProps | Record<string, unknown> | Props spread onto every <Select> |
| perLevelProps | Partial<Record<SelectLevel, Record<string, unknown>>> | Per-level prop overrides keyed by 'country' \| 'province' \| 'district' \| 'city' |
MuiLocationPicker additional props
| Prop | Type | Description |
|---|---|---|
| autocompleteProps | Record<string, unknown> | Props spread onto every <Autocomplete> |
| textFieldProps | Record<string, unknown> | Props spread onto every <TextField> |
| perLevelProps | Partial<Record<SelectLevel, { autocomplete?; textField? }>> | Per-level overrides |
Angular Location Picker
A standalone PrimeNG cascade picker for Angular 17+. Ships as raw TypeScript source — no build step required.
PrimeNG version compatibility
| PrimeNG version | Component to import | Selector |
|---|---|---|
| v17 – v19 | LocationPickerComponent | <cdf-location-picker> |
| v20+ | LocationPickerSelectComponent | <cdf-location-picker-select> |
PrimeNG v20 removed primeng/dropdown (p-dropdown). The LocationPickerSelectComponent uses primeng/select (p-select) which is required for v18+.
Peer dependencies
npm install @angular/core @angular/common @angular/forms primeng rxjsSetup
Add the source path to your tsconfig.json:
{
"include": [
"src",
"node_modules/country-data-filter/src/angular/**/*.ts"
]
}Import
Both components are exported from the main barrel. Import by name — TypeScript will resolve the correct file:
PrimeNG v17–v19:
import { LocationPickerComponent } from 'country-data-filter/angular';PrimeNG v20+:
import { LocationPickerSelectComponent } from 'country-data-filter/angular';Add to your component's imports array (both are standalone components):
// PrimeNG v17-v19
@Component({
standalone: true,
imports: [LocationPickerComponent],
template: `<cdf-location-picker [countryControl]="countryCtrl" />`
})
// PrimeNG v20+
@Component({
standalone: true,
imports: [LocationPickerSelectComponent],
template: `<cdf-location-picker-select [countryControl]="countryCtrl" />`
})Basic usage — reactive forms
countryCtrl = new FormControl(null);
provinceCtrl = new FormControl(null);
districtCtrl = new FormControl(null);
cityCtrl = new FormControl(null);<cdf-location-picker
[countryControl]="countryCtrl"
[provinceControl]="provinceCtrl"
[districtControl]="districtCtrl"
[cityControl]="cityCtrl">
</cdf-location-picker>Event-driven (no reactive forms)
<cdf-location-picker
(countryChange)="onCountry($event)"
(provinceChange)="onProvince($event)"
(cityChange)="onCity($event)">
</cdf-location-picker>onCountry(e: CountryChangeEvent) {
console.log(e.formValue); // country code (or custom value key)
console.log(e.country); // full Country object
}
onCity(e: CityChangeEvent) {
console.log(e.name); // city name
console.log(e.postalCode); // postal code string
console.log(e.type); // "City" | "Town" | "Village"
}Which dropdowns appear
Dropdowns are shown based on which controls are passed:
| Inputs provided | Dropdowns shown |
|---|---|
| [countryControl] only | Country |
| + [provinceControl] | Country → Province |
| + [districtControl] | Country → Province → District |
| + [cityControl] | Country → Province → District → City |
Passing [cityControl] automatically implies all levels above it.
Custom option values
<!-- value = dialling code, e.g. "+94" for Sri Lanka -->
<cdf-location-picker countryValueKey="countryCode" [countryControl]="ctrl" />
<!-- label shows currency code -->
<cdf-location-picker countryLabelKey="currency" [countryControl]="ctrl" />PrimeNG prop passthrough
v17–v19 — use *DropdownProps inputs:
<cdf-location-picker
[countryControl]="countryCtrl"
[countryDropdownProps]="{ styleClass: 'w-full', appendTo: 'body', showClear: true }"
[provinceDropdownProps]="{ styleClass: 'w-full', filter: false }">
</cdf-location-picker>v20+ — use *SelectProps inputs (same object shape):
<cdf-location-picker-select
[countryControl]="countryCtrl"
[countrySelectProps]="{ styleClass: 'w-full', appendTo: 'body', showClear: true }"
[provinceSelectProps]="{ styleClass: 'w-full', filter: false }">
</cdf-location-picker-select>Layout
<!-- v17-v19 -->
<cdf-location-picker layout="horizontal" [countryControl]="ctrl" />
<!-- v20+ -->
<cdf-location-picker-select layout="horizontal" [countryControl]="ctrl" />Inputs reference
Both components share the same inputs — the only difference is *DropdownProps vs *SelectProps:
| Input | Type | Default | Description |
|---|---|---|---|
| countryControl | AbstractControl | — | Reactive form control for country |
| provinceControl | AbstractControl | — | Reactive form control for province; presence shows province dropdown |
| districtControl | AbstractControl | — | Reactive form control for district |
| cityControl | AbstractControl | — | Reactive form control for city |
| countryLabelKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'name' | Field to use as dropdown label |
| countryValueKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'code' | Field to use as option value |
| countryDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the country <p-dropdown> |
| provinceDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the province <p-dropdown> |
| districtDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the district <p-dropdown> |
| cityDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the city <p-dropdown> |
| countrySelectProps (v20+) | SelectProps | {} | Props spread onto the country <p-select> |
| provinceSelectProps (v20+) | SelectProps | {} | Props spread onto the province <p-select> |
| districtSelectProps (v20+) | SelectProps | {} | Props spread onto the district <p-select> |
| citySelectProps (v20+) | SelectProps | {} | Props spread onto the city <p-select> |
| layout | 'vertical' \| 'horizontal' | 'vertical' | Flex direction of the wrapper |
Outputs reference
| Output | Event type | Description |
|---|---|---|
| (countryChange) | CountryChangeEvent | Emits { formValue, country } on country select |
| (provinceChange) | NameChangeEvent | Emits { name } on province select |
| (districtChange) | NameChangeEvent | Emits { name } on district select |
| (cityChange) | CityChangeEvent | Emits { name, postalCode, type } on city select |
Event types
interface CountryChangeEvent {
formValue: string | null; // what was written to the FormControl
country: Country | null; // full Country object (always raw, regardless of valueKey)
}
interface NameChangeEvent {
name: string | null;
}
interface CityChangeEvent {
name: string | null;
postalCode: string; // empty string when not available
type?: string; // "City" | "Town" | "Village"
}Supported Countries
The package covers all 190 UN-recognized sovereign states, including:
| Region | Examples | |--------|---------| | Asia | IN, CN, JP, VN, BD, PK, ID, TH, PH, KR, TR, SA, IR, IQ, MM, AF, KZ, UZ | | Africa | NG, ET, EG, CD, TZ, KE, ZA, GH, MZ, CM, CI, AO, ML, SD, MG | | Europe | DE, FR, GB, IT, ES, PL, RO, NL, BE, CZ, GR, PT, HU, AT, CH, SE | | Americas | US, BR, MX, CA, CO, AR, PE, VE, CL, EC, BO, PY, UY, CU, DO | | Oceania | AU, NZ, PG, FJ, SB, VU, WS, TO, TV, PW, NR, KI |
TypeScript Support
Full TypeScript typings are included via src/index.d.ts. Key interfaces:
interface Country {
name: string;
code: string;
currency: string;
countryCode: string; // international dialling code, e.g. "+1"
provinceLabel: string; // e.g. "State", "Province", "Region"
districtLabel: string; // e.g. "County", "District", "Governorate"
}
interface City {
name: string;
postalCode: string;
type?: "City" | "Town" | "Village";
}
interface District {
name: string;
cities: City[];
}
interface Province {
name: string;
districts: Record<string, District>;
}Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-change) - Make your changes and add tests where applicable
- Submit a pull request with a clear description
Repository: github.com/knnadeera/country-data
License
ISC
Contact
For questions or support: [email protected]
