0

I have this service that observes changes via an interval by using a GET request to my API:

package used: https://github.com/Asymmetrik/ngx-leaflet

Coords.ts model

export class Coords {
constructor(public lat: number,
          public lng: number,
          public code: string,
          public uuid: string) {}
}

map.service.ts

@Injectable()
export class RealTimeDataService {

constructor(private http: HttpClient) { }


private dataSubject: BehaviorSubject<Coords[]> = new 
BehaviorSubject([]);

data$: Observable<Coords[]> = this.dataSubject.asObservable();

updateData(): Observable<any>  {
return this.getData().do((data) => {
  this.dataSubject.next(data);
 });
}


// My data is an array of model objects
getData(): Observable<Coords[]>{
const headers = new HttpHeaders({'Content-Type':'application/json; charset=utf-8', 'code':'0T86MIT'});
return this.http.get(`${AUTH_API_URL}/user/coords`, {headers: headers})
  .map((response: Coords[]) => {
    let data = response;
    if(data){
      return data;
    }
  })
 }
}

And this is the map component:

map.component.ts

export class MapComponent implements OnInit, OnDestroy {

constructor(private realTimeDataService: RealTimeDataService, private 
zone: NgZone) {
}

LAYER_OSM = 
tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 
{maxZoom: 18, attribution: '&copy; <a 
 href="http://osm.org/copyright">OpenStreetMap</a> contributors'});
 markers: Layer[] = [];

options = {
 layers: [this.LAYER_OSM],
 zoom  : 13,
 center: latLng(38.274452, 21.755992)
};

private unsubscribe: Subject<any> = new Subject();
private subscription: Subscription;

data: Coords[];
interval: any;

ngOnInit() {
 this.refreshData();
 if (this.interval) {
  clearInterval(this.interval);
}
 this.interval = setInterval(() => {
  this.refreshData();
   }, 2000);


this.realTimeDataService.data$.takeUntil(this.unsubscribe)
  .subscribe(data => {
    this.zone.run(() => {

      this.data = data;
     // this.markers = [];
      if (data.length > 0) {
        data.map((a, index) => {
          let lat = a.lat;
          let lng = a.lng;
          let uuid = a.uuid;

          const newMarker = marker(
            [lat, lng],
            {
              icon: icon({
                iconSize  : [25, 41],
                iconAnchor: [13, 41],
                iconUrl   : 'assets/marker-icon.png',
                shadowUrl : 'assets/marker-shadow.png'
              })
            }
          );
          newMarker.bindPopup('<p>' + uuid + '</p>', {autoPan: true});
          this.markers.push(newMarker);
        });
      }
      // console.log('sub', data);
    });
  });
}

ngOnDestroy() {
 this.unsubscribe.next();
 this.unsubscribe.complete();
}

refreshData() {
 this.realTimeDataService.updateData()
  .takeUntil(this.unsubscribe)
  .subscribe();
 }
}

map.component.html

<div class="map-padding" *ngIf="data.length > 0">
 <div style="height: 1000px;"
   leaflet
   [leafletOptions]="options"
   [leafletLayers]="markers">
 </div>
</div>

Every time the data that contains the lat,lng refreshes then the old markers are not being removed. If I set this.markers = [] is a workaround but if the user clicks the marker, the popup stays open for 2 seconds (until the new data comes in). How can i persist popup being open when new data comes in?

preview of the issue: (i just clicked once, popup disappears automagically when new data comes in)

enter image description here

EDIT:

other than that, is there a way to tell the observable to stop/pause streaming if the new data is the same as the old one?

Stathis Ntonas
  • 1,222
  • 2
  • 20
  • 49
  • I think your problem is caused by the fact you are either pushing new objects to the array, of creating a completely new array. That way your Leaflet component is never aware of a marker being updated. You need to update the original marker object, by changing the latitude and longitude of this specific object inside your array. Otherwise the reference is lost. – enf0rcer Mar 01 '18 at 10:14
  • Can you share an example? – Stathis Ntonas Mar 01 '18 at 12:40
  • I can't, I dont know anything about Leaflet or the marker() function. Without that its impossible to create a good example. But look at the scrips file in this example: https://plnkr.co/edit/M1vR5S0NoUjTHMLwblGR?p=catalogue – enf0rcer Mar 01 '18 at 13:35
  • As @user3492940 says, it looks like you're replacing the marker, which will cause leaflet to remove the old marker and add the new one. That will cause the popup to collapse. So, you'd have to add your own logic to only add markers that are actually new, remove markers that are no longer shown, and leave the existing markers where they are. – reblace Mar 01 '18 at 22:27

0 Answers0