Geolocalización y APIs: Creando un Mapa de Tiendas Cercanas
Clase 25 de 36 • Curso de Angular Avanzado
Contenido del curso
- 7

Buenas prácticas con variables locales en Angular
09:14 - 8

Optimización de Imágenes en Angular con NG Optimizate Image
17:08 - 9

Optimización de Rutas Amigables para SEO en Angular
11:27 - 10

"Reactividad en Angular: Migración a Input Signals"
20:42 - 11

Migración de Inputs a Signals en Angular: Mejora de Rendimiento y Flujo
12:24 - 12

Migración de Outputs en Angular: De Decoradores a Funciones
07:35 - 13

Primitivas reactivas de Angular: Uso de Linked Signal y Computed
12:56 - 14

Sincronización de Componentes en Angular con Model y Signals
12:03 - 15

Interoperabilidad de RXJS y Signals en Angular
11:18 - 16

Conversión de Observables a Signals en Angular con toSignal
08:07 - 17

Interoperabilidad de RXDS y Signals en Angular: Uso de RX Resourcers
11:10 - 18

Manejo de Parámetros Reactivos con RX Resource en Angular
09:18 - 19

Manejo de Promesas y Fetch en Angular sin RXJS
07:59 - 20

Reactividad en Angular: Uso de Signals para Consultas DOM
09:00 - 21

Configuración de Prettier para HTML en Angular
05:28 quiz de Nuevas Funcionalidades en Angular
- 22

Server Side Rendering en Angular: Builders y Migración
10:17 - 23

Server Side Rendering con Angular: Mejora Rendimiento y SEO
13:26 - 24

Manejo de APIs del Navegador con Angular: Uso de AfterNextRender
09:43 - 25

Geolocalización y APIs: Creando un Mapa de Tiendas Cercanas
15:39 - 26

Habilitar Pre-rendering en Angular para Generación de Sitios Estáticos
11:26 - 27

Despliegue de Aplicaciones Node.js con App Fiber Hosting
18:12 quiz de Server-Side Rendering (SSR) y Navegación
- 28

Generación de Meta Tags Dinámicos con Angular y Open Graph
15:11 - 29

Creación de MetaTags Dinámicos en Angular
12:51 - 30

Proceso de Hydration y Event Replay en Angular
05:54 - 31

Implementación de Productos Relacionados en Angular eCommerce
09:26 - 32

Carga diferida de componentes en Angular para mejorar rendimiento
10:10 - 33

Optimización de Incremental Hydration en Angular
06:14 - 34

Configuración de Server Routing en Angular
10:43 - 35

Aplicaciones Sin Zone.js: Migración a Signals en Angular
13:02 - 36

Despliegue y Reactividad Avanzada en Angular
00:53
La geolocalización es una herramienta poderosa que permite a las aplicaciones web ofrecer experiencias personalizadas basadas en la ubicación del usuario. Mediante el uso de APIs nativas del navegador y servicios externos, podemos crear funcionalidades que muestren información relevante según la posición geográfica del visitante. En este artículo, exploraremos cómo implementar la geolocalización en una aplicación Angular para mostrar puntos de interés cercanos a la ubicación del usuario, una característica común en sitios de eCommerce que desean mostrar sus tiendas físicas.
¿Cómo funciona la API de geolocalización del navegador?
La API Navigator.geolocation es una interfaz nativa de los navegadores modernos que permite acceder a la ubicación geográfica del dispositivo. Esta API solo funciona del lado del cliente (browser) y requiere el consentimiento explícito del usuario para compartir su ubicación.
Para utilizar esta API en Angular, debemos asegurarnos de ejecutar el código relacionado con la geolocalización después de que el componente se haya renderizado en el navegador:
import { Component, Signal, signal } from '@angular/core';
import { afterNextRender } from '@angular/core';
@Component({
selector: 'app-locations',
templateUrl: './locations.component.html'
})
export class LocationsComponent {
origin: Signal<string> = signal('');
constructor() {
afterNextRender(() => {
navigator.geolocation.getCurrentPosition((position) => {
const newOrigin = `${position.coords.latitude},${position.coords.longitude}`;
this.origin.set(newOrigin);
});
});
}
}
El método getCurrentPosition() devuelve un objeto con las coordenadas del usuario, que podemos formatear según nuestras necesidades. En este caso, creamos un string con el formato "latitud,longitud" que utilizaremos para consultar una API externa.
¿Por qué usar afterNextRender?
Es crucial utilizar afterNextRender cuando trabajamos con APIs que solo están disponibles en el navegador, ya que Angular utiliza renderizado universal (server-side rendering) para la primera carga. Esto garantiza que el código de geolocalización solo se ejecute cuando el componente esté completamente renderizado en el cliente.
¿Cómo consumir una API de localización con las coordenadas del usuario?
Una vez obtenida la ubicación del usuario, podemos utilizarla para consultar una API que nos proporcione puntos de interés cercanos. En nuestro ejemplo, utilizaremos un endpoint de la API de Platzi que acepta parámetros como:
- origin: Coordenadas de origen en formato "latitud,longitud"
- size: Cantidad de puntos a devolver
- radius: Radio de búsqueda (en kilómetros)
Implementación del consumo de la API
async locationResource(request: { origin?: string } = {}) {
const url = new URL(`${environment.API_URL}/api/v1/localizations`);
if (request.origin) {
url.searchParams.set('origin', request.origin);
}
const response = await fetch(url.toString());
return await response.json();
}
Este método recibe un objeto con parámetros opcionales y construye la URL de la petición utilizando la API URL, que nos permite agregar query params de forma sencilla. Si existe un origen, lo añadimos como parámetro a la URL.
Renderizando los resultados en el componente
Para mostrar los puntos de interés en nuestra interfaz, podemos utilizar un bucle en nuestro template:
<ul>
@for (location of locations; track location.id) {
<li>{{ location.name }}</li>
}
</ul>
¿Cómo mejorar la arquitectura de nuestra aplicación?
Aunque el código anterior funciona correctamente, no sigue las mejores prácticas de Angular. Es recomendable separar la lógica de negocio (obtención de datos) de la presentación (componente) siguiendo el principio de responsabilidad única de SOLID.
Creando un servicio dedicado
La forma correcta de implementar esta funcionalidad sería crear un servicio dedicado:
import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class LocationsService {
async getLocations(params: { origin?: string, size?: number, radius?: number } = {}) {
const url = new URL(`${environment.API_URL}/api/v1/localizations`);
// Añadir parámetros si existen
if (params.origin) url.searchParams.set('origin', params.origin);
if (params.size) url.searchParams.set('size', params.size.toString());
if (params.radius) url.searchParams.set('radius', params.radius.toString());
const response = await fetch(url.toString());
return await response.json();
}
async getCurrentPosition(): Promise<string> {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(
(position) => {
const coords = `${position.coords.latitude},${position.coords.longitude}`;
resolve(coords);
},
(error) => {
reject(error);
}
);
});
}
}
Este servicio encapsula toda la lógica relacionada con la obtención de la ubicación del usuario y la consulta a la API de localización, lo que hace que nuestro componente sea más limpio y mantenible.
Utilizando el servicio en el componente
import { Component, Signal, signal } from '@angular/core';
import { afterNextRender } from '@angular/core';
import { LocationsService } from './locations.service';
@Component({
selector: 'app-locations',
templateUrl: './locations.component.html'
})
export class LocationsComponent {
locations: Signal<any[]> = signal([]);
constructor(private locationsService: LocationsService) {
// Cargar ubicaciones por defecto
this.loadLocations();
// Cargar ubicaciones basadas en la posición del usuario
afterNextRender(async () => {
try {
const origin = await this.locationsService.getCurrentPosition();
this.loadLocations({ origin });
} catch (error) {
console.error('Error obteniendo la ubicación:', error);
}
});
}
async loadLocations(params = {}) {
const data = await this.locationsService.getLocations(params);
this.locations.set(data);
}
}
Esta implementación es más robusta y sigue las mejores prácticas de Angular, separando claramente las responsabilidades entre el componente y el servicio.
La geolocalización es una herramienta poderosa que puede mejorar significativamente la experiencia de usuario en aplicaciones web. Al implementarla correctamente en Angular, podemos ofrecer contenido personalizado basado en la ubicación del usuario de manera eficiente y mantenible. ¿Has implementado funcionalidades de geolocalización en tus proyectos? Comparte tu experiencia en los comentarios.