Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BehaviorSubject.next does not update view with async pipe

I try to retrieve Google Places with Google Places Js API and use BehaviorSubject.next to update my Angular view with the async pipe but view is not updating.

Actually sometimes it does after 15 sec. sometimes I have to click somewhere. But what I sure about is that it doesn't update the moment I get results from Google servers... (I console log it).

Here is my search function:

    import { AfterViewInit, Component, ViewChild, ElementRef } from '@angular/core';
import { LoadingController, NavParams, ViewController, Platform } from 'ionic-angular';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
declare var google;

@Component({
  selector: 'page-new-location-modal',
  templateUrl: 'new-location-modal.html'
})
export class NewLocationModalPage {

  @ViewChild('map') map: ElementRef;

  // ngModel for segment
  googleSearchType: string;

  // Sport retrieved from previous page (newEventForm)
  sport = '';

  // Props used for suggestion func
  mapElem: ElementRef;
  googleService: any;
  places$:BehaviorSubject<any[]>= new BehaviorSubject([]);


  constructor(
    public platform: Platform,
    public viewCtrl: ViewController,
    public loadingCtrl: LoadingController,
    public params: NavParams
  ) {
    console.log('NewLocationModal#constructor');

    // Sport must be retrieved from params
    this.sport = params.get('sport');
  }

  ngAfterViewInit(): void {
    // Init Google service
    this.mapElem = this.map.nativeElement;
    this.googleService = new google.maps.places.PlacesService(this.mapElem);

    // Select Suggestion segment
    this.googleSearchType = 'suggestion';
    // Trigger searchSuggestionsForSport()
    this.searchSuggestionsForSport(this.sport);

  }

  onSegmentChange(segment): void {
    console.log('NewLocationModal#onSegmentChange - Selected segment ', segment.value);

    if (segment.value === 'suggestion') {
      this.searchSuggestionsForSport(this.sport);
    }
  }

  searchSuggestionsForSport(sport: string): void {
    console.log('NewLocationModal#searchSuggestionsForSport - Sport ', sport);

    let location = new google.maps.LatLng(48.862725,2.287592000000018);
    let request = {
      location: location,
      keyword: sport,
      rankBy: google.maps.places.RankBy.DISTANCE
    };

    // Google Places Service


    // NearBy Search
    this.googleService.nearbySearch(request, (places) => {
      // First set of information sent to the async pipe in view
      this.places$.next(places);

      console.log(places);
    });
  }

  dismiss() {
    this.viewCtrl.dismiss();
  }
}

And view:

<div *ngFor="let place of places$ | async">
          <ion-card>
            <ion-card-content>
              <ion-card-title>
                {{place.name}} - {{place.rating}}
              </ion-card-title>
              <p>
                {{place.vicinity}}
              </p>
            </ion-card-content>
          </ion-card>
        </div>

Any solution?

like image 415
Manuel RODRIGUEZ Avatar asked May 19 '17 11:05

Manuel RODRIGUEZ


1 Answers

Google Maps is known to make code run outside Angulars zone, this "breaks" change detection. Make the code that updates the model run within Angulars zone explicitly:

 constructor(
    public platform: Platform,
    public viewCtrl: ViewController,
    public loadingCtrl: LoadingController,
    public params: NavParams,
    private zone:NgZone,
  ) {

...

    // NearBy Search
    this.googleService.nearbySearch(request, (places) => {
      // First set of information sent to the async pipe in view
      this.zone.run(() => this.places$.next(places));
      console.log(places);
    });  
like image 181
Günter Zöchbauer Avatar answered Sep 29 '22 08:09

Günter Zöchbauer