Leaflet marker not appearing when using observables - javascript

map.component.ts
export class MapComponent implements AfterViewInit {
private map;
private centroid: L.LatLngExpression = [49.2827, -123.1207];
private initMap(): void {
this.map = L.map('map', {
center: this.centroid,
zoom: 12
});
const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
minZoom: 3,
attribution: '© OpenStreetMap'
});
tiles.addTo(this.map);
}
constructor(private _dataService: DataService) {
}
ngAfterViewInit(): void {
this.initMap();
this._dataService.pigMessage$.subscribe(message => {
L.marker([49.2827, -123.1207]).addTo(this.map).bindPopup("test").openPopup();
console.log(message);
})
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs';
import { pigReportType } from './pigReport';
#Injectable({
providedIn: 'root'
})
export class DataService {
private _pigMessageSource = new Subject<pigReportType>();
pigMessage$ = this._pigMessageSource.asObservable();
sendPigData(message: pigReportType){
this._pigMessageSource.next(message)
}
constructor() { }
}
When I click on the submit button, data service sends a new piece of information into the observable and redirects back to the map component. The problem is the marker is not adding inside of the subscribe function in map.component.ts.
Additionally, I have checked that the .subscribe function works because it prints the correct message. The markers just do not appear on the map.
I have tried looking through the html and seeing if there is a duplicated map that is covering the map with the marker but there isn't. Also I have tried to call initMap inside of the .subscribe function but it doesn't work.
I'm hoping if someone can point me in the right direction because I have searched everywhere on the web for a solution but can't find it.

Related

HERE maps in angular show a blank map

even when I use the exact example of here map official site I received a blank view, only with HERE logo and the rest of this layer.
I received a "WebGL warning: uniform setter: No active linked Program." warning on my firefox and VSC debug console.
I changed the navigator to Chrome and Opera, and I received the same result.
My apikey is alright, I test it on postman and it worked.
This my code
import { Component, ElementRef, OnInit, ViewChild, Input } from '#angular/core';
declare var H: any;
#Component({
selector: 'here-map',
templateUrl: './heremap.component.html',
styleUrls: ['./heremap.component.scss'],
})
export class HeremapComponent implements OnInit {
#ViewChild("map") public mapElement: ElementRef;
#Input() private _apikey: any;
#Input() public lat: any;
#Input() public lng: any;
#Input() public width: any;
#Input() public height: any;
private map: any;
constructor() { }
ngOnInit() {}
public ngAfterViewInit() {
console.log('HERE apikey: ', this._apikey);
let platform = new H.service.Platform({
apikey: this._apikey
});
let defaultLayers = platform.createDefaultLayers();
this.map = new H.Map(this.mapElement.nativeElement,
defaultLayers.vector.normal.map,
{
zoom: 10,
center: { lat: this.lat, lng: this.lng }
}
);
this.map.setCenter({lat: 52.5159, lng: 13.3777});
this.map.setZoom(14);
}
}
<div class="here-maps" #map [style.width]="width" [style.height]="height"></div>
I was having the same issue, and I fixed it by resizing the map after it was fully loaded.
You must trigger the resize event after 500ms (or something like that) at the end of the ngAfterViewInit() event:
This is an example of my code:
setTimeout(function () {
window.dispatchEvent(new Event('resize'));
}, 500);
In the resize event, you should resize the map:
#HostListener('window:resize', ['$event'])
onResize(event: any) {
requestAnimationFrame(() => this.map.getViewPort().resize());
}
After this, all is working as expected:

Leaflet - import Geojson - Angular 6

i try to import GeoJson file to leaflet in angular's app 6.
With this solution my geojson is drawn in leafletmap but i have this error and i can't build my app. Someone know one solution ?
ERROR TS2345 Argument of type '{"type": string;"features":({"type":
string; "geometry": { "type: string : "coordinates": num...' is not
assignable parameter of type GeoJsonObject
Model.ts
export const Pdl = [ 'my geojson' ];
https://raw.githubusercontent.com/alanent/france-geojson/master/regions/pays-de-la-loire/departements-pays-de-la-loire.geojson
Component.ts
import { LeafletModule } from '#asymmetrik/ngx-leaflet';
import * as L from 'leaflet';
import {Pdl} from "../models/pdl.model";
#Component({
selector: 'app-geo',
templateUrl: './geo.component.html',
styleUrls: ['./geo.component.scss']
})
export class GeoComponent implements OnInit {
ngOnInit() {
var mapboxAccessToken = "...";
const myfrugalmap = L.map('frugalmap').setView([47.482019, -1], 7);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=' + mapboxAccessToken, {
id: 'mapbox.light',
attribution: 'SOS'
}).addTo(myfrugalmap);
L.geoJSON(Pdl).addTo(myfrugalmap);
}
}
Maybe, i can hide the error ? what is the way ?
You need to do it the 'angular way' since you are using ngx-leaflet
Importing a json via import is a nightmare in my personal opinion so what I would do would be to fetch it using a get request when the map is loaded and then get a reference to the map object and add the geojson.
template:
import { HttpClient } from '#angular/common/http';
import * as L from 'leaflet';
..
map: L.Map;
json;
options = {
layers: [
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18, attribution: '...'
})
],
zoom: 7,
center: L.latLng(47.482019, -1)
};
constructor(private http: HttpClient) { }
onMapReady(map: L.Map) {
this.http.get('assets/departements.json').subscribe((json: any) => {
console.log(json);
this.json = json;
L.geoJSON(this.json).addTo(map);
});
}
template
<div leaflet style="height: 800px"
[leafletOptions]="options"
(leafletMapReady)="onMapReady($event)">
</div>
Demo

Openlayers map undefined in a class

I'm kinda new in an angular (and javascript generally). I have this code
import {Injectable, OnInit} from '#angular/core';
import OlMap from 'ol/map';
import OSM from 'ol/source/osm'
import OlXYZ from 'ol/source/xyz';
import OlTileLayer from 'ol/layer/tile';
import OlView from 'ol/view';
import OlProj from 'ol/proj';
#Injectable()
export class MapService {
public map: OlMap;
private _source: OlXYZ;
private _layer: OlTileLayer;
private _view: OlView;
constructor() { }
/**
* Function initializes the map
* #returns {} Object of map
*/
initMap() {
this._source = new OSM({
});
this._layer = new OlTileLayer({
source: this._source
});
this._view = new OlView({
center: OlProj.fromLonLat([6.661594, 50.433237]),
zoom: 10,
});
this.map = new OlMap({
target: 'map',
layers: [this._layer],
view: this._view
});
this.map.on("moveend", function () {
console.log(this.map);
})
}
}
The problem is on the last line. I'm trying to console log the object of map on moveend (so when user drag the map and release button- I want to load some data depends on the center of a map). But the console says the object this.map is undefined (even I'm calling a method on that object and It's working fine- It's called on mouse button release.
I guess It's gonna be something javascript special, some local or global object references, etc.
Can anyone help me, please?
NOTE: the initMap() method is called in the map component like this
ngOnInit() {
this.map = this.mapService.initMap();
console.log(this.mapService.map);
}
(In this console.log case its working fine, there is object of type _ol_map)
Your problem is the diff between function () {} and () => {}.
In function () {}, the context of "this" is the caller of the function so here is "OlMap".
In () => {}, the context of "this" is where you create it so here is "MapService".
this.map doesn't exist in OlMap.
To fix your issue, simply replace function () by () => into this.map.on().

Ionic 3 Google Maps Integration

I am following this tutorial exactly: https://www.djamware.com/post/58f4da2080aca7414e78a638/step-by-step-tutorial-of-ionic-3-angular-4-and-google-maps-directions-service
But I cannot get it to work. I have the API key set up no problem, but for some reason I keep getting the error Error: Uncaught (in promise): ReferenceError: google is not defined
ReferenceError: google is not defined
I am running the app using ionic lab
For some reason it isn't working. Can someone help me find the problem? I have tried adding the cordova whitelist plugin, changing the https to http in the API key part, but still it isn't working.
Did you declare the variable at home.ts?
import { Component, ViewChild, ElementRef } from '#angular/core';
import { IonicPage } from 'ionic-angular';
import { NavController } from 'ionic-angular';
declare var google;
#IonicPage()
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
...
Ionic 3 Google Map click doc link
1.install this package
$ ionic cordova plugin add https://github.com/mapsplugin/cordova-plugin-googlemaps#multiple_maps --variable API_KEY_FOR_ANDROID="YOUR_ANDROID_API_KEY_IS_HERE" --variable API_KEY_FOR_IOS="YOUR_IOS_API_KEY_IS_HERE"
$ npm install --save #ionic-native/google-maps
2.Android and ios Api create
Go to this site - google cloud platform
3.After you got Api install packages
4.import
app.module.ts
import { GoogleMaps } from '#ionic-native/google-maps';
......
provider:[
GoogleMaps
];
5.home.html
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<div id="map"></div>
</ion-content>
6.home.ts
import { Component } from '#angular/core';
import { NavController, Platform } from 'ionic-angular';
import {
GoogleMaps,
GoogleMap,
GoogleMapsEvent,
LatLng,
CameraPosition,
MarkerOptions,
Marker
} from '#ionic-native/google-maps';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController,
private googleMaps: GoogleMaps,
public platform: Platform) {
platform.ready().then(()=>{
this.loadMap();
})
}
loadMap() {
// create a new map by passing HTMLElement
let element: HTMLElement = document.getElementById('map');
let map: GoogleMap = this.googleMaps.create(element);
// listen to MAP_READY event
// You must wait for this event to fire before adding something to the map or modifying it in anyway
map.one(GoogleMapsEvent.MAP_READY).then(
() => {
console.log('Map is ready!');
// Now you can add elements to the map like the marker
}
);
// create CameraPosition
let position: CameraPosition = {
target: {
lat: 43.0741904,
lng: -89.3809802
},
zoom: 18,
tilt: 30
};
// move the map's camera to position
map.moveCamera(position);
// create new marker
let markerOptions: MarkerOptions = {
//position: ionic,
title: 'Ionic'
};
map.addMarker(markerOptions)
.then((marker: Marker) => {
marker.showInfoWindow();
});
}
}

Angular 2, child component using with google maps events losing context

I have a case when I am using component in component. By accessing properties of child component via #ViewChild, I am getting undefined for methods in child component.
// Parent component
declare var google: any;
#Component({
selector: 'app-map',
templateUrl: `
<div id="map"></div>
<app-context-menu></app-context-menu>`,
styleUrls: ['./map.component.css'],
providers: [CitiesService],
})
export class MapComponent implements AfterViewInit {
#ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
user: UserInterface;
city: any;
map: any;
constructor(
private userStorage: UserStorage,
private citiesService: CitiesService,
private theMap: TheMap,
) {}
ngAfterViewInit() {
this.findUserCityCoords();
}
inittializeMap(mapOpts) {
let mapProps = {
center: new google.maps.LatLng(mapOpts.lat, mapOpts.lng),
zoom: mapOpts.zoom,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
let map = new google.maps.Map(document.getElementById('map'), mapProps);
let menu = this.contextMenu;
map.addListener('rightclick', (e) => {
console.log('map', this);
console.log('menu', this.contextMenu);
this.contextMenu.open(e);
});
}
findUserCityCoords() {
let userCity = this.userStorage.getFromStorage().city;
this.citiesService.getCityConfig()
.subscribe(cities => {
cities.forEach(city => {
if (city.name === userCity) this.inittializeMap(city.center);
});
});
}
From this class when 'map event listener' calls 'menu.open(e);' the context changes and inside child component, the methods of child component are not available. To call i.e. 'this.draw()' method.
// Child component
import { Component, OnInit, ElementRef, AfterViewInit } from
'#angular/core';
import { TheMap } from '../../services/mapServices/TheMap';
import { Marker } from '../../services/mapServices/marker.service';
declare var google: any;
#Component({
selector: 'app-context-menu',
templateUrl: './context-menu.component.html',
styleUrls: ['./context-menu.component.css']
})
export class ContextMenuComponent {
overlay;
el;
constructor(
private theMap: TheMap,
private marker: Marker,
private elementRef: ElementRef
) {
this.overlay = new google.maps.OverlayView();
}
ngAfterViewInit() {}
open(e) {
let map = this.theMap.getMap();
this.overlay.set('position', e.latLng);
this.overlay.setMap(map);
this.draw(); // <---- Here, this.draw() is not a function
// So I can access properties from constructor but not this.draw() and other methods of this class
};
draw() {
// ....
}
How can I properly implement google's map 'rightclick' event listener (probably with 'bind') to use my child's component methods. Thanks
Not sure I understand the question but () => (arrow function) might be what you're looking for
map.addListener('rightclick', (e) => {
console.log('map', this);
console.log('menu', menu);
this.contextMenu.open(e);
});

Categories