Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

125
Vistas
ngFor don`t show all items immediately after place_changed event from google place autocomplete

I need to add result to the list after place_changed event. I display the list below the input in which I find locations. Event works and result is pushed to array items. But the problem is that new added item don`t display immediately. It displayed after some time or when I click on form where this input is displayed.

.ts:

  @ViewChild('locationInput', { static: true }) input: ElementRef;
  autocomplete;
  items = [];
 ngOnInit() {
    this.autocomplete = new google.maps.places.Autocomplete(this.input.nativeElement, this.localityOptions);
    this.autocomplete.addListener('place_changed', () => {
      this.addToListSelectedItem();
    });
  }

  public addToListSelectedItem() {
    if (this.input.nativeElement.value) {
      this.items.push(this.input.nativeElement.value);
      this.input.nativeElement.value = '';
    }
  }

.html:

 <input
      #locationInput
      class="shadow-none form-control"
      formControlName="locality"
      placeholder=""
      [attr.disabled]="locationForm.controls['region'].dirty ? null : true"
    />
<div *ngFor="let item of items; let index = index">
      <div class="listOfLocation">
        <div class="itemList">{{ item }}</div>
        <img [src]="icons.cross" class="delete-button-img" alt="edit-icon" (click)="deleteTask(index)" />
      </div>
    </div>

Thanks for the help!

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Probably your component Change Detection Strategy is OnPush or google autocomplete is running outside zone.js:

 changeDetection: ChangeDetectionStrategy.OnPush

And since items is array and it is stored in memory by reference you need to run manually change detenction:

constructor(private cdr: ChangeDetectorRef)

public addToListSelectedItem() {
  ...
  this.input.nativeElement.value = '';
  this.cdr.detectChanges();
about 4 years ago · Juan Pablo Isaza Denunciar

0

Even better would be to work with an RxJS Subject, an Observable for items$ and use the async pipe. The async pipe works like magic what concerns updating the template :-)!

@ViewChild('locationInput', { static: true }) input: ElementRef;
autocomplete;
itemsSubject$ = new Subject<any[]>();   
items$ = this.itemsSubject$.asObservable();
// Use a separate array to hold the items locally:
existing = [];

ngOnInit() {
    this.autocomplete = new google.maps.places.Autocomplete(this.input.nativeElement, this.localityOptions);
    this.autocomplete.addListener('place_changed', () => {
      this.addToListSelectedItem();
    });
  }

public addToListSelectedItem() {
    if (this.input.nativeElement.value) {
       // Use spread syntax to create a new array with the input value pushed at the end:
       this.existing = [...this.existing, this.input.nativeElement.value];
       // Send the newly created array to the Subject (this will update the items$ Observable since it is derived from this Subject): 
       this.itemsSubject$.next(this.existing);
       this.input.nativeElement.value = '';
    }
  }

// I added the deleteTask implementation to show you how this works with the subject:
deleteTask(index: number) {
    // The Array "filter" function creates a new array; here it filters out the index that is equally to the given one:
    this.existing = this.existing.filter((x, i) => i !== index);
    this.itemsSubject$.next(this.existing);
  }

And in the template:

<input
      #locationInput
      class="shadow-none form-control"
      formControlName="locality"
      placeholder=""
      [attr.disabled]="locationForm.controls['region'].dirty ? null : true"
    />
<!-- Only difference here is adding the async pipe and using the items$ Observable instead -->
<div *ngFor="let item of items$ | async; let index = index">
      <div class="listOfLocation">
        <div class="itemList">{{ item }}</div>
        <img [src]="icons.cross" class="delete-button-img" alt="edit-icon" (click)="deleteTask(index)" />
      </div>
    </div>

For a working example of the RxJS Subject in this concept, see https://stackblitz.com/edit/angular-ivy-dxfsoq?file=src%2Fapp%2Fapp.component.ts.

Maybe beyond this question, but since you're using a reactive form, why not use this.locationForm.get('locality').setValue('...') to set the input instead of using a ViewChild for working with the input? More control this way then using the ViewChild.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda