---
title: "Vue Select Country Dropdown Example | Mobiscroll"
component: "Select"
framework: "Vue"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/vue/select/country-picker"
---

# Country Dropdown - Vue Select demo

Vue Country picker scroller select for mobile/tablet. Alphabetical ordering, jump to value and filtering is supported. For Vue and Nuxt.

- [Live demo](https://demo.mobiscroll.com/vue/select/country-picker)
- [View SFC JS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue/tree/main/src/demos/pickers/select/country-picker)
- [View SFC TS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue-ts/tree/main/src/demos/pickers/select/country-picker)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/select/country-picker.md), [jQuery](https://demo.mobiscroll.com/jquery/select/country-picker.md), [Angular](https://demo.mobiscroll.com/angular/select/country-picker.md), [React](https://demo.mobiscroll.com/react/select/country-picker.md)

## Description

Use the select component as a country picker on mobile and desktop. You can add the dropdown to any input or use [Mobiscroll input fields](https://demo.mobiscroll.com/vue/forms/inputs-text-areas-date-fields). If you don't want to make it a dropdown, you can embed the picker inline right into a page.

Search is enabled through the [`filter` option](https://mobiscroll.com/docs/vue/select/api#opt-filter).

In this example the data is loaded from a remote JSON in the following format: `{ "value": "FJ", "group": "F", "text": "Fiji" }` and the flags are loaded from our server. For your implementation you should embed the list and flags into your own page.

For the image & text rendering use a [custom item template](https://demo.mobiscroll.com/vue/select/item-templating).

## What this demo shows

- A searchable country dropdown built with the select component.
- **Select inputs** Focusing or clicking an input opens its picker.
- **Dropdown behavior** The picker opens below the input and closes when the user clicks outside it.
- **Filtering** A search bar in the picker header filters the country list by name.
- **Picker content** Each option in the predefined list displays a country flag and country name.
- **Hover state** Hovering over an option highlights it in the picker.
- **Selection** Selecting an option marks it with a checkmark to indicate the current value.
- **Scrolling** The dropdown supports scrolling through the full list of countries.
- **Input value** Selecting a country updates the associated input with that value.

## Best for

- **Registration and onboarding** Letting users find and select their country when creating an account or profile.
- **Address forms** Adding a searchable country field to billing, shipping, or contact details.
- **Checkout flows** Helping customers choose a destination or billing country from a long list.
- **Regional settings** Selecting a country for locale, market, or account preferences.
- **Mobile and desktop forms** Providing a consistent country selection experience across screen sizes.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/vue/select/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/vue/select/api#opt-themeVariant) - option
- [`data`](https://mobiscroll.com/docs/vue/select/api#opt-data) - option
- [`itemHeight`](https://mobiscroll.com/docs/vue/select/api#opt-itemHeight) - option
- [`label`](https://mobiscroll.com/docs/vue/select/api#opt-label) - option
- [`display`](https://mobiscroll.com/docs/vue/select/api#opt-display) - option
- [`inputStyle`](https://mobiscroll.com/docs/vue/select/api#opt-inputStyle) - option
- [`labelStyle`](https://mobiscroll.com/docs/vue/select/api#opt-labelStyle) - option

## Code

### SFC JS

```vue
<script setup>
import { getJson, MbscPage, MbscSelect, setOptions } from '@mobiscroll/vue'
import { onMounted, ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myData = ref([])

onMounted(() => {
  getJson('https://trial.mobiscroll.com/content/countries.json', (resp) => {
    const countries = []
    for (let i = 0; i < resp.length; ++i) {
      const country = resp[i]
      countries.push({ text: country.text, value: country.value })
    }
    myData.value = countries
  })
})
</script>

<template>
  <MbscPage>
    <MbscSelect
      :data="myData"
      :itemHeight="40"
      label="Countries"
      display="anchored"
      inputStyle="box"
      labelStyle="stacked"
      placeholder="Please select..."
    >
      <template #item="item">
        <div class="md-country-picker-item">
          <img
            class="md-country-picker-flag"
            :src="'https://img.mobiscroll.com/demos/flags/' + item.data.value + '.png'"
          />
          {{ item.display }}
        </div>
      </template>
    </MbscSelect>
  </MbscPage>
</template>

<style>
.md-country-picker-item {
  position: relative;
  line-height: 20px;
  padding: 10px 0 10px 40px;
}

.md-country-picker-flag {
  position: absolute;
  left: 0;
  height: 20px;
}

.mbsc-scroller-wheel-item-2d .md-country-picker-item {
  transform: scale(1.1);
}
</style>
```

### SFC TS

```vue
<script setup lang="ts">
import { getJson, MbscPage, MbscSelect, setOptions } from '@mobiscroll/vue'
import { onMounted, ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myData = ref<any>([])

onMounted(() => {
  getJson('https://trial.mobiscroll.com/content/countries.json', (resp: any) => {
    const countries = []
    for (let i = 0; i < resp.length; ++i) {
      const country = resp[i]
      countries.push({ text: country.text, value: country.value })
    }
    myData.value = countries
  })
})
</script>

<template>
  <MbscPage>
    <MbscSelect
      :data="myData"
      :itemHeight="40"
      label="Countries"
      display="anchored"
      inputStyle="box"
      labelStyle="stacked"
      placeholder="Please select..."
    >
      <template #item="item">
        <div class="md-country-picker-item">
          <img
            class="md-country-picker-flag"
            :src="'https://img.mobiscroll.com/demos/flags/' + item.data.value + '.png'"
          />
          {{ item.display }}
        </div>
      </template>
    </MbscSelect>
  </MbscPage>
</template>

<style>
.md-country-picker-item {
  position: relative;
  line-height: 20px;
  padding: 10px 0 10px 40px;
}

.md-country-picker-flag {
  position: absolute;
  left: 0;
  height: 20px;
}

.mbsc-scroller-wheel-item-2d .md-country-picker-item {
  transform: scale(1.1);
}
</style>
```

## Implementation notes

- `data` takes an array of `{ value, text, group? }` objects; this demo fetches it at runtime from a remote JSON endpoint and maps each raw record to `{ text: country.text, value: country.value }` before passing it in.
- `filter: true` (Angular `[filter]="true"`) enables the built-in client-side search box in the picker header, which filters the `data` array by `text` as the user types; no `onFilter` handler is wired up in this demo since filtering stays local.
- `display="anchored"` opens the picker as a dropdown anchored below the input instead of a modal/bottom-sheet.
- The flag image per option is rendered through a custom item template, not a `data` field: the template builds each flag's URL from `item.data.value` (the ISO country code) against a fixed `https://img.mobiscroll.com/demos/flags/<value>.png` pattern, and renders `item.display` (the resolved label) next to it.
- Custom item markup differs per framework: React passes a `renderItem` function prop returning JSX for `(item: MbscSelectItemData)`; JS/jQuery pass a `renderItem` function option returning an HTML string; Angular uses `[itemTemplate]="itemTemp"` pointing at a named `<ng-template #itemTemp let-item>` with `item.data`/`item.display` available in scope; Vue uses the `#item` named slot on `<MbscSelect>` with `item.data`/`item.display` exposed as slot props.
- `itemHeight` must be set to match the custom template's rendered row height (`40` here) so the virtualized/scrollable list measures rows correctly.
- `inputStyle`/`labelStyle` (`"outline"`/`"stacked"` or similar) and `placeholder` are cosmetic input-decoration options, not select-specific behavior.
- For production use, the flags and country list should be hosted in the consuming app rather than loaded from the demo's `img.mobiscroll.com`/`trial.mobiscroll.com` endpoints.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-vue.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config vue
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config vue --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/vue/getting-started/installation

## Related demos

- Previous: [Templating](https://demo.mobiscroll.com/vue/select/item-templating.md) - Vue select component & dropdown with templating capability. Render custom content for each item, like image & text.
- Next: [Image & text](https://demo.mobiscroll.com/vue/select/image-text.md) - Vue select with custom item templates rendering in image & text. Build custom UI, not just plain text/value picker.
