Implementar formularios reactivos con type ahead

Clase 70 de 80Curso de Angular 4

Resumen

Conecta un campo de búsqueda con resultados en tiempo real de Google usando Angular, RxJS y Bootstrap. Aquí verás cómo estructurar el HTML, activar formularios reactivos, renderizar una lista con async y optimizar llamadas con debounceTime para un type ahead fluido y veloz.

¿Cómo implementar type ahead con Angular, RxJS y Google?

Primero, se prepara el HTML para capturar la entrada y mostrar resultados. El input se enlaza a un FormControl llamado searchField. Cada tecla genera eventos que, vía RxJS, hacen la llamada al API de Google, formatean la respuesta y alimentan un stream de resultados. Se renderiza una lista con Bootstrap y el async pipe para manejar la naturaleza asíncrona.

¿Cómo se pinta la lista con async y Bootstrap?

  • Input de texto con clase de Bootstrap para estilo.
  • Directiva reactiva [formControl] enlazada a searchField.
  • Lista sin ordenar con clases list-group y list-group-item.
  • Iteración con ngFor sobre results$ usando el async pipe.
<form>
  <div class="well">
    <label>Buscar negocio en Google.</label>
    <input type="text" class="form-control" [formControl]="searchField" />

    <ul class="list-group">
      <li class="list-group-item" *ngFor="let result of results$ | async">
        {{ result.formatted_address }}
      </li>
    </ul>
  </div>
</form>
  • La propiedad mostrada es formatted_address del API de Google: dirección legible para humanos.
  • Tip: revisar clases de Bootstrap para que se apliquen estilos correctos.

¿Qué error de Angular aparece y cómo se corrige?

Al usar [formControl] puede aparecer: "Can't bind to 'formControl' since it isn't a known property of 'input'". Causa: los formularios reactivos no se cargan por defecto. Solución: importar ReactiveFormsModule en AppModule.

// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
  ]
})
export class AppModule {}
  • Tras guardar y recargar, el input ya actúa como control reactivo.
  • Útil abrir la pestaña Network en Chrome para observar el stream de llamadas.

¿Cómo reducimos llamadas y mejoramos performance?

Teclear rápido dispara muchos requests; incluso algunos fallan. Para evitar saturación, se usa debounceTime antes de switchMap. Así se espera un tiempo entre teclas y solo se ejecuta la última intención del usuario.

// crear.component.ts (fragmento)
this.results$ = this.searchField.valueChanges.pipe(
  debounceTime(500),
  switchMap(term => this.search(term)),
  map(resp => this.format(resp)),
  map(list => this.onlyAddresses(list))
);
  • debounceTime(500): espera medio segundo entre eventos de tecleo antes de llamar al API.
  • Aún es rápido y reduce drásticamente la cantidad de requests.

¿Qué operadores se concatenan y para qué sirven?

  • debounceTime: controla frecuencia de eventos para mejorar rendimiento.
  • switchMap: cancela búsquedas anteriores y usa solo la más reciente.
  • map (dos veces): transforma la respuesta y extrae los datos necesarios.
  • async (pipe en plantilla): suscribe y desuscribe automáticamente al stream; ideal para datos asíncronos y escenarios con sockets en RxJS.

¿Qué sigue para completar la experiencia?

Al hacer clic en un resultado, se puede autocompletar el formulario con: calle y número, ciudad y país. El API ya provee esa data en address_components (por ejemplo: street_number, long_name). La tarea consiste en capturar el clic en el ítem y poblar esos inputs.

  • Ejemplos probados: "Universidad Nacional" y "Juárez dos" muestran múltiples resultados bien formateados.
  • Habilidades aplicadas: Angular Reactive Forms, RxJS operators, Bootstrap, manejo de API de Google, diagnóstico con Network.

¿Te animas a implementar el clic en la lista y llenar las tres cajas? Comparte tu código y una captura en los comentarios para revisar juntos.

      Implementar formularios reactivos con type ahead