diff --git a/frontend/src/components/Map.vue b/frontend/src/components/Map.vue
index 9139ebd..416272d 100644
--- a/frontend/src/components/Map.vue
+++ b/frontend/src/components/Map.vue
@@ -120,13 +120,12 @@ import FloatingButton from '../elements/FloatingButton.vue';
 import GPSPoint from '../models/GPSPoint';
 import LocationQuery from '../models/LocationQuery';
 import LocationQueryMixin from '../mixins/LocationQuery.vue';
-import LocationStats from '../models/LocationStats';
 import MapSelectOverlay from './MapSelectOverlay.vue';
 import MapView from '../mixins/MapView.vue';
 import Paginate from '../mixins/Paginate.vue';
 import Points from '../mixins/Points.vue';
 import Routes from '../mixins/Routes.vue';
-import StatsRequest from '../models/StatsRequest';
+import StatsMixin from '../mixins/Stats.vue';
 import Timeline from './Timeline.vue';
 import TimelineMetricsConfiguration from '../models/TimelineMetricsConfiguration';
 import URLQueryHandler from '../mixins/URLQueryHandler.vue';
@@ -143,6 +142,7 @@ export default {
     Paginate,
     Points,
     Routes,
+    StatsMixin,
     URLQueryHandler,
   ],
 
@@ -314,22 +314,6 @@ export default {
       await this.processQueryChange(this.locationQuery, oldQuery)
     },
 
-    async getCountries(): Promise<Country[]> {
-      return (
-        await this.getStats(
-          new StatsRequest({
-            // @ts-ignore
-            userId: this.$root.user.id,
-            groupBy: ['country'],
-            order: 'desc',
-          })
-        )
-      )
-      .filter((record: LocationStats) => !!record.key.country)
-      .map((record: LocationStats) => Country.fromCode(record.key.country))
-      .filter((country: Optional<Country>) => !!country)
-    },
-
     createMap(): Map {
       this.pointsLayer = this.createPointsLayer(Object.values(this.mappedPoints) as Point[])
       this.routesLayer = this.createRoutesLayer(Object.values(this.mappedPoints) as Point[])
diff --git a/frontend/src/components/filter/Form.vue b/frontend/src/components/filter/Form.vue
index fcff5a0..efae992 100644
--- a/frontend/src/components/filter/Form.vue
+++ b/frontend/src/components/filter/Form.vue
@@ -167,13 +167,10 @@
           </p>
         </label>
 
-        <Autocomplete
-          id="country"
-          name="country"
+        <CountrySelector
           placeholder="Filter by country"
-          allow-only-values
           :value="newFilter.country || ''"
-          :values="autocompleteCountries"
+          :countries="countries"
           :disabled="disabled"
           @input="newFilter.country = $event" />
       </div>
@@ -274,9 +271,8 @@
 <script lang="ts">
 import _ from 'lodash'
 
-import Autocomplete from '../../elements/Autocomplete.vue'
-import AutocompleteValue from '../../models/AutocompleteValue'
 import Country from '../../models/Country'
+import CountrySelector from '../../elements/CountrySelector.vue'
 import LocationQuery from '../../models/LocationQuery'
 import LocationQueryMixin from '../../mixins/LocationQuery.vue'
 import UserDevice from '../../models/UserDevice'
@@ -289,7 +285,7 @@ export default {
   ],
 
   components: {
-    Autocomplete,
+    CountrySelector,
   },
 
   props: {
@@ -313,13 +309,6 @@ export default {
   },
 
   computed: {
-    autocompleteCountries(): AutocompleteValue[] {
-      return this.countries.map((country: Country) => ({
-        value: country.code,
-        label: `${country.flag} ${country.name}`,
-        data: country,
-      }))
-    },
     maxDate() {
       return this.toLocalString(this.endPlusHours(new Date(), 0))
     }
diff --git a/frontend/src/elements/CountrySelector.vue b/frontend/src/elements/CountrySelector.vue
new file mode 100644
index 0000000..f7aad57
--- /dev/null
+++ b/frontend/src/elements/CountrySelector.vue
@@ -0,0 +1,139 @@
+<template>
+  <div class="country-selector">
+    <Loading v-if="loading" />
+    <Autocomplete
+      :id="id"
+      :name="name"
+      :placeholder="placeholder"
+      :value="value"
+      :values="autocompleteCountries"
+      :disabled="disabled || loading"
+      allow-only-values
+      @input="onInput" />
+  </div>
+</template>
+
+<script lang="ts">
+import { countries } from 'countries-list'
+
+import Autocomplete from './Autocomplete.vue'
+import AutocompleteValue from '../models/AutocompleteValue'
+import Country from '../models/Country'
+import Loading from './Loading.vue'
+import Stats from '../mixins/Stats.vue'
+
+export default {
+  mixins: [Stats],
+  components: {
+    Autocomplete,
+    Loading,
+  },
+
+  props: {
+    countries: {
+      type: Array as () => Country[],
+    },
+
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
+
+    id: {
+      type: String,
+      default: 'country',
+    },
+
+    name: {
+      type: String,
+      default: 'country',
+    },
+
+    placeholder: {
+      type: String,
+      default: 'Select a country',
+    },
+
+    showAll: {
+      type: Boolean,
+      default: false,
+    },
+
+    value: {
+      type: String,
+      default: '',
+    },
+  },
+
+  data() {
+    return {
+      countries_: this.countries ? [...this.countries] : [],
+      loading: false,
+    }
+  },
+
+  computed: {
+    autocompleteCountries(): AutocompleteValue[] {
+      const visitedCountries = this.countries_.reduce(
+        (acc: Record<string, AutocompleteValue>, country: Country) => {
+          acc[country.code] = this.toAutocompleteValue(country)
+          return acc
+        }, {}
+      );
+
+      if (!this.showAll) {
+        return Object.values(visitedCountries)
+      }
+
+      const unvisitedCountries = Object.keys(countries).reduce(
+        (acc: Record<string, AutocompleteValue>, key: string) => {
+          if (visitedCountries[key]) {
+            return acc
+          }
+          acc[key] = this.toAutocompleteValue(countries[key])
+          return acc
+        }, {}
+      )
+
+      return [
+        ...Object.values(visitedCountries) as AutocompleteValue[],
+        ...Object.values(unvisitedCountries) as AutocompleteValue[],
+      ]
+    },
+  },
+
+  methods: {
+    onInput(value: string) {
+      this.$emit('input', value)
+    },
+
+    toAutocompleteValue(country: {
+      code: string
+      name: string
+      flag: string
+    }): AutocompleteValue {
+      return new AutocompleteValue({
+        value: country.code,
+        label: `${country.flag} ${country.name}`,
+        data: country,
+      })
+    },
+  },
+
+  created: function () {
+    if (!this.countries) {
+      this.getCountries().then((countries: Country[]) => {
+        this.countries_ = countries
+      })
+    }
+  },
+}
+</script>
+
+<style scoped lang="scss">
+.country-selector {
+  position: relative;
+  width: 100%;
+  margin: 0 auto;
+}
+</style>
diff --git a/frontend/src/mixins/Stats.vue b/frontend/src/mixins/Stats.vue
new file mode 100644
index 0000000..7040151
--- /dev/null
+++ b/frontend/src/mixins/Stats.vue
@@ -0,0 +1,26 @@
+<script lang="ts">
+import type { Optional } from '../models/Types';
+import Country from '../models/Country';
+import LocationStats from '../models/LocationStats';
+import StatsRequest from '../models/StatsRequest';
+
+export default {
+  methods: {
+    async getCountries(): Promise<Country[]> {
+      return (
+        await this.getStats(
+          new StatsRequest({
+            // @ts-ignore
+            userId: this.$root.user.id,
+            groupBy: ['country'],
+            order: 'desc',
+          })
+        )
+      )
+      .filter((record: LocationStats) => !!record.key.country)
+      .map((record: LocationStats) => Country.fromCode(record.key.country))
+      .filter((country: Optional<Country>) => !!country)
+    },
+  },
+}
+</script>