Aprende a implementar un autocompletado de direcciones con Google que rellena calle, ciudad y país de forma automática. Verás cómo una directiva de clic dispara la función seleccionar dirección y cómo realizar el binding de los datos del record al modelo. Además, se cierra el tema de RxJS y se anticipa el despliegue en Firebase hosting.
¿Cómo funciona el autocompletado y el binding de campos?
Al escribir el nombre del negocio o una dirección y elegir una sugerencia, los tres campos del formulario se completan sin esfuerzo. La clave está en capturar el resultado completo que devuelve Google y mapearlo a los atributos del lugar que vas a guardar.
Escribir el nombre del negocio o dirección en el input.
Hacer clic en una sugerencia de autocompletado.
Rellenado automático de calle y número, ciudad y país.
Proceso simple de replicar con pequeños ajustes.
Enfoque centrado en pasar el resultado completo del record seleccionado.
¿Qué hace la directiva de clic y la función seleccionar dirección?
En el HTML se define una directiva de clic que ejecuta la función seleccionar dirección. Como parámetro, se envía el resultado completo que llega de Google para el record seleccionado. Así se evita perder información relevante durante el mapeo.
La función imprime la selección para inspeccionar qué contiene.
Se asignan los atributos del lugar: calle, ciudad y país.
Se realiza el binding directo de cada parte del resultado a su campo correspondiente.
El objetivo es guardar un objeto de lugar coherente y completo.
¿Qué sigue con RxJS y hosting en Firebase?
Con esta implementación queda cerrado el tema de RxJS en el flujo de autocompletado y data binding. El siguiente paso es preparar el despliegue: subir la aplicación al hosting de Firebase, optimizando así el proceso de publicación.
¿Quieres profundizar en el mapeo de datos del autocompletado o en el despliegue en Firebase hosting? Comparte tus dudas y comentarios para seguir la conversación.
Esta fue mi solucion, ya que el objeto que te retorna la api de Google Maps las posiciones varian del array ‘addressComponents’, habria que ver en el array de ‘types’ si cuenta con el que necesitamos.
Aca dejo el codigo que me funciono a mi
html
<h3>Datos de direccion</h3><div class="well"><form><label for="">BuscarNegocio en Google</label><input input="text"class="form-control"[formControl]="searchField"></form><ul class="list-group"><li *ngFor="let result of results$ | async"class="list-group-item"(click)="llenarDatosDireccion(result)">{{result.formatted_address}}</li></ul></div><label>Calle y Número</label><input type="text"class="form-control"[(ngModel)]="lugar.calle"><br><label>Ciudad</label><input type="text"class="form-control"[(ngModel)]="lugar.ciudad"><br><label>Pais</label><input type="text"class="form-control"[(ngModel)]="lugar.pais">
ts
llenarDatosDireccion(direccion: any){let calle = direccion.address_components.find(element=> element.types[0]==='route')||{long_name:''};let numero = direccion.address_components.find(element=> element.types[0]==='street_number')||{long_name:''};let ciudad = direccion.address_components.find(element=> element.types[0]==='administrative_area_level_2')||{long_name:''};let pais = direccion.address_components.find(element=> element.types[0]==='country')||{long_name:''};this.lugar.calle=`${calle.long_name}${numero.long_name}`;this.lugar.ciudad= ciudad.long_name;this.lugar.pais= pais.long_name;}
Aquí les dejó mi solución, ya que los indexes no siempre coinciden con el campo que buscamos:
privateselectResult(result){const addressComponents = result.address_components;this.place.street=`${this.findPlaceInResults('route', addressComponents)}${this.findPlaceInResults('street_number', addressComponents)}`;this.place.city=this.findPlaceInResults('locality', addressComponents);this.place.country=this.findPlaceInResults('country', addressComponents);}privatefindPlaceInResults(place, addressComponents){const result = addressComponents.find(address=> address.types.includes(place));return result ? result.long_name:'';}
Solucion:
seleccionarDireccion(result){const addressComponents = result.address_componentsconstadrressParams: any ={}for(let i =0, len = addressComponents.length; i < len; i++){const type = addressComponents[i].types[0].toString()switch(type){case'street_number': adrressParams.street_number= addressComponents[i].long_namebreakcase'route': adrressParams.route= addressComponents[i].long_namebreakcase'locality': adrressParams.locality= addressComponents[i].long_namebreakcase'country': adrressParams.country= addressComponents[i].long_namebreak}}this.lugar.calle=`${adrressParams.route}${adrressParams.street_number}`this.lugar.ciudad= adrressParams.localitythis.lugar.pais= adrressParams.country}
codigo interesante
Estoy usando ngbTypeahead y no he podido limpiar el campo de texto cuando no se selecciona un elemento de la lista que trae, alguna sugerencia??
Lanza algún error en consola, o simplemente no hace nada?