Refreshing ion-list when model gets dynamically updated


#1

Hi,
I’m struggling to figure out an easy way from my controller (.ts file) to refresh the ion-list in the view once the model, in my case an array of items is dynamically updated via an api.

Any help would be appreciated.

thanks
Vinit


#2

You shouldn’t have to do anything special here. Something is unusual in your code.


#3

Thanks Robert.
I have a list as described in code snippet below

<ion-searchbar [(ngModel)]="searchQuery" id="place_search" (input)="getItems($event)"placeholder=“Type in your current location”>

<ion-list> <ion-item *ngFor="#item of items" (click)="insertSelectLocationItem()"> {{ item }} </ion-item> </ion-list>

A searchbar that trigger an api call. The results from the call will set the items. I’m not able to figure out how to reload the list after the items have been updated. If i click on the list in UI, the list gets refreshed and the latest items are shown.

Thanks once again for all your help


#4

We need to see how items is being updated.


#5

so the serach bar string trigger a google api call

var service = new google.maps.places.PlacesService(map);
service.nearbySearch(request,(results, status) => {
if (status == google.maps.places.PlacesServiceStatus.OK) {

  items = []; // reset the model

  for (var i = 0; i < results.length; i++) {
    items.push(results[i].name)

  }
}

#6

I think your problem is that the Google Places library isn’t zone-aware. You could make a Promise wrapper with something like this (I don’t know if there are typings for this library, so sorry for the any's):

export class PlacesService {
  nearbySearch(map:any, request:any):Promise<string[]> {
    return new Promise<any>((resolve, reject) => {
      let gplaces = new google.maps.places.PlacesService(map);
      gplaces.nearbySearch(request, (results, status) => {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
          resolve(results);
        } else {
          reject(status);
        }
      });
    }).then((places) => {
      return places.map((place) => place.name);
    });
  }
}
export class MyPage {
  items:string[];

  constructor(private places:PlacesService) {
  }

  doSearch(map:any, request:any) {
    this.places.nearbySearch(map, request).then((places) => {
      this.items = places;
    });    
  } 
}

Totally untested, so sorry for bugs, but should get you started.


#7

Thank you so much for this. I totally didnt think about this and can see how it could work. I’ll give it a shot tonight and let you know how it goes. Really appreciate it!!


#8

Robert you totally made my day. I got it working in a few mins. Thank you so much for guiding me in the right direction. Thank you !!!


#9

Here is the working code

    export class GooglePlacesService {

      /**
       * Helper method to get google places by search query
       * @param {string} query : query sting to search for 
       * @return {google.maps.places.PlaceResult[]} results : array of places once the promise
       * is fullfilled
       */
      getPlacesBySearch(query: string): Promise<google.maps.places.PlaceResult[]> {
        return new Promise<any>((resolve, reject) => {
          var request = {
            componentRestrictions: { country: "us" },
            types: ['restaurant'],
            query: query
          };
          // a dummy container since i just need the results
          var container = <HTMLDivElement>document.getElementById('results');

          var service = new google.maps.places.PlacesService(container);
          return service.textSearch(request, (results, status) => {
            if (status == google.maps.places.PlacesServiceStatus.OK) {
              resolve(results);
            } else {
              reject(status);
            }
          });
        });
      }

      /**
       * Helper method to get google places by search query
       * @param {number} lat : lat location value 
       * @param {number} long : long location value 
       * @return {google.maps.places.PlaceResult[]} results : array of places once the promise
       * is fullfilled
       */
      getPlaceNearBy(lat: number, long: number): Promise<google.maps.places.PlaceResult[]> {
        return new Promise<any>((resolve, reject) => {
          var __this = this,
            request = {
              location: new google.maps.LatLng(lat, long),
              types: ['restaurant'],
              radius: 2000
            };
          // a dummy container since i just need the results
          var container = <HTMLDivElement>document.getElementById('results');

          var service = new google.maps.places.PlacesService(container);
          return service.nearbySearch(request, (results, status) => {
            if (status == google.maps.places.PlacesServiceStatus.OK) {
              resolve(results);
            } else {
              reject(status);
            }
          });
        });
      }
    }

you invoke these methods by

    import {Geolocation} from 'ionic-native';
    import {GooglePlacesService} from './google-places';

    googlePlaces: GooglePlacesService = new GooglePlacesService() ;

    Geolocation.getCurrentPosition().then((resp) => {
          this.googlePlaces.getPlaceNearBy(resp.coords.latitude, resp.coords.longitude)
            .then((places) => this.items = places)
            .catch(error => {
              console.log(error);
            });
        });

#10

Thanks for coming back to post this. A small suggestion: don’t instantiate services like GooglePlacesService directly with new. Instead declare them in your app’s custom providers and let Angular’s dependency injection system manage their lifecycle.