HB's Thoughts

I try to think really hard.

11/28/2024

Simple Vue plugin for geo location

When I write a plugin, I think of it as a standalone piece of code that has its own logic and is independent of where it will be used. This is not entirely true, of course, but when designing a plugin, I always start from this idea. After all, every system has its own logic and architecture that must be followed - especially for outgoing data.

Geo location

In modern browsers, it is very easy to access the Geolocation API. You call

navigator.geolocation.getCurrentPosition(call_success_function, call_error_function);

and in the object returned to call_success_function you will get everything you need, including latitude & longitude. If necessary, you can check if the browser supports the Geolocation API if (!navigator.geolocation) { ... } else { ... }.

I will add a small abstraction to the standard function to make it work in an asynchronous environment.

async function GeoLocation(): Promise<GeolocationCoordinates> {
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      (success) => resolve(location.coords),
      (error) => reject(error)
    );
  });
}

A wonderful method that will return the coordinates and (as I told you at the beginning) works regardless of the environment in which it will be used.

Vue plugin

In a project where we want to use the above method as a plugin, I create a folder plugins and in it I create a sub-folder geo-location. In this folder I add 2 files - index.ts and GeoLocation.ts. Of course, the content of GeoLocation.ts is the above method.

// plugins/geo-location/GeoLocation.ts

export async function GeoLocation(): Promise<GeolocationCoordinates> {
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      (success) => resolve(location.coords),
      (error) => reject(error)
    );
  });
}

In index.ts I follow the standard structure of Vue plugins.

// plugins/geo-location/index.ts

import type { App } from "vue";
import { GeoLocation } from "./GeoLocation";

export default {
  install(app: App) {
    app.provide("GeoLocation", GeoLocation);
  },
};

Then we add it to main.ts.

// main.ts

import { createApp } from "vue";
import App from "./App.vue";
import GeoLocationPlugin from "./plugins/geo-location";

const app = createApp(App);

app.use(GeoLocationPlugin);
app.mount("#app");

Using the plugin

Here is the reason for writing this article. To use the plugin in a TypeScript environment, you need to be careful with the initialization in the Vue component where you will use it.

const GEOLocation = inject<() => Promise<GeolocationCoordinates>>('GeoLocation');

If you omit the cast () => Promise<GeolocationCoordinates>, you will get an error that GeoLocation is not a function.


You can also define your own type:
type GeoLocationType = () => Promise<GeolocationCoordinates>;
const GEOLocation = inject<GeoLocationType>('GeoLocation');

If you have an opinion or questions about the article, don't hesitate to share them.

Join the open discussion on GitHub.


Competence: Geek