Angular2/ionic2 angular2-google-maps error Cannot find name 'google' - google-maps

I followed the this example (click here) to make a field of address with autocompletion of google map Places,
But it's giving the following error:
Can not find name 'google'.
L53: this.mapsAPILoader.load (). Then (() => {
L54: let autocomplete = new google.maps.places.Autocomplete
(this.searchElementRef.nativeElement, {
I tried to install google-maps types npm install --save #types/google-maps but it is without results.
After installing #types/google-maps the build is ok but when I luanch i have this error :
Cannot find name 'google' after installing #types/google-maps
My Code :
import { FormControl } from '#angular/forms';
import { Component, ViewChild, OnInit, ElementRef } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { MapsAPILoader } from 'angular2-google-maps/core';
#Component({
selector: 'page-page2',
templateUrl: 'page2.html'
})
export class Page2 implements OnInit {
latitude: number = 51.678418;
longitude: number = 7.809007;
zoom: number = 4;
searchControl: FormControl;
#ViewChild("search")
searchElementRef: ElementRef;
constructor(public navCtrl: NavController, public navParams: NavParams, private mapsAPILoader: MapsAPILoader) {
// some not related to this question code
}
ngOnInit() {
//create search FormControl
this.searchControl = new FormControl();
//set current position
this.setCurrentPosition();
//load Places Autocomplete
this.mapsAPILoader.load().then(() => {
let autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement, {
types: ["address"]
});
autocomplete.addListener("place_changed", () => {
//get the place result
let place: google.maps.places.PlaceResult = autocomplete.getPlace();
//set latitude and longitude
this.latitude = place.geometry.location.lat();
this.longitude = place.geometry.location.lng();
});
});
}
private setCurrentPosition() {
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition((position) => {
this.latitude = position.coords.latitude;
this.longitude = position.coords.longitude;
this.zoom = 12;
});
}
}
}

Run typings install dt~google.maps --global
as found here

Related

Trying to Add Markers to Leaflet Map with button click (Using Angular)

I have the following code where I am creating a leaflet map on initial load of the page. I have about four jsons with lat/lon data that I would like to populate the map. What I'm looking for is four buttons that when clicked will add the json data as markers to the map.
What I'm getting is an error indicating the following:
Cannot read properties of undefined (reading 'addLayer').
Map Component:
import { Component, AfterViewInit, OnInit } from '#angular/core';
import { MapPointsService } from './map-points.service';
import * as L from 'leaflet';
#Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css'],
})
export class MapComponent implements AfterViewInit {
private map: L.Map | L.LayerGroup<any> | undefined;
area: any;
markersLayer = new L.LayerGroup();
private initMap(): void {
this.map = L.map('map', {
center: [4.5709, -74.2973],
zoom: 3,
});
this.area = this.map;
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 mapService: MapPointsService) {}
ngAfterViewInit(): void {
this.initMap();
// this.mapService.jsonMarkers(this.area);
}
addMarkers(): void {
this.mapService.jsonMarkers(this.area);
}
}
MapService
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
// import { MapComponent } from './map.component';
import * as L from 'leaflet';
#Injectable({
providedIn: 'root',
})
export class MapPointsService {
constructor(private http: HttpClient) {}
jsonMarkers(map: L.Map): void {
this.http
.get('/assets/data/<my_json>.json')
.subscribe((res: any) => {
for (const area of res.<json_item>) {
const lon = are.Longitude;
const lat = are.Latitude;
const marker = L.marker([lat, lon]);
/*if (map.hasLayer(marker)) {
map.removeLayer(marker);
}*/
marker.addTo(map);
// console.log(markers);
}
});
}
}
Info Component that calls function
import { Component, OnInit } from '#angular/core';
import { MapPointsService } from '../map/map-points.service';
import { MapComponent } from '../map/map.component';
import { MatSnackBar } from '#angular/material/snack-bar';
#Component({
selector: 'app-information',
templateUrl: './information.component.html',
styleUrls: ['./information.component.css'],
})
export class InformationComponent implements OnInit {
/**
* showSpinner boolean
*/
showSpinner = false;
constructor(
private _snackBar: MatSnackBar,
private mapService: MapPointsService
) {}
ngOnInit(): void {}
run(msg: string): void {
const snackBarRef = this._snackBar.open('Running ' + msg, 'Close', {
duration: 3000,
});
snackBarRef.afterDismissed().subscribe(() => {
this.showSpinner = false;
});
this.showSpinner = true;
}
mapData() {
let data = new MapComponent(this.mapService);
data.addMarkers();
}
}
Info Html
<button type="button" (click)='mapData()'></button>
If you manually instantiate an Angular component with just the new keyword (let data = new MapComponent(this.mapService)), it will not be mounted anywhere, and in particular its lifecycle methods, like ngAfterViewInit, will not be called.
Then in your case, this.map and this.area remain undefined, leading to your error message.
Since you do not show your templates, it is hard to tell how your components are supposed to be related.
In case your <app-information> (InformationComponent) contains the <app-map> (MapComponent), you can use #ViewChild in InformationComponent to get a reference to the child MapComponent, and from there you can call its addMarkers method.
In case they are in the opposite situation, IIRC you can just request a MapComponent type in InformationComponent constructor, and Angular will inject it from its ancestors tree.
And if they are somehow siblings, then you could manage from a common ancestor:
get a ref to the MapComponent as described first
add an #Output event emitter on InformationComponent that fires when your button is clicked, and in the ancestor you listen to that event, and call the MapComponent.addMarkers method.

How can I get the real image value from each item in my list and subscribe it to another list?

I have a list of services that have multiple property like serviceId, serviceName and photoProfile called from a database using a spring REST API.
The 'photoProfile' property only has the id of the profile picture which if you use the 'localhost:8082/downloadFile/'+photoProfile would get you the image which is in turn is stored in a folder in the spring project.
After looking for a while online, I've found how I can actually get the real image to display on my website but now I'm stuck since I need to do this for the whole list.
Here's my angular code:
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { LoginComponent } from '../login/login.component';
import { UserService } from '../user.service';
import { Observable, forkJoin } from 'rxjs';
import { HttpHeaders, HttpClient } from '#angular/common/http';
import { combineLatest } from 'rxjs/operators';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
loggedIn: boolean;
services: any[] = [];
imgSrc: any;
newList: any[] = [];
constructor(private router: Router, private service: UserService, private http: HttpClient) {
}
ngOnInit() {
this.service.getServices().subscribe(res => {
this.services = res;
console.log('services: ', this.services);
});
for (let i = 0; i < this.services.length; i++) {
const element = this.services[i];
this.getImage('http://localhost:4200/downloadFile/' + element.photoProfile).subscribe(data => {
this.createImageFromBlob(data);
});
this.newList.push(this.imgSrc);
console.log(this.newList);
//I want to add the element from the services list and the image value after being converted to the new list
}
}
getImage(imageUrl: string): Observable<Blob> {
return this.http.get(imageUrl, {responseType: 'blob'});
}
createImageFromBlob(image: Blob) {
const reader = new FileReader();
reader.addEventListener('load', () => {
this.imgSrc = reader.result;
}, false);
if (image) {
reader.readAsDataURL(image);
}
}
}
Thank you for your help.
You need to add the new list inside the ngOnInit after you are subscribing to the services list. Because currently. You don't have the services when the for loop runs. You need to run the for loop after you have the result from services. Like this:
ngOnInit() {
this.service.getServices().subscribe(res => {
this.services = res;
console.log('services: ', this.services);
for (let i = 0; i < this.services.length; i++) {
const element = this.services[i];
this.getImage('http://localhost:4200/downloadFile/' + element.photoProfile).subscribe(data => {
this.createImageFromBlob(data);
element.imgSrc = this.imgSrc;
this.newList.push(element);
});
console.log(this.newList);
}
}
});
I had similar situation, and method of Muhammad Kamran work particularry for me, because images loaded into array absolutely randomly. As i understand, the speed of FOR cycle is faster than picture download speed. The solution is - pushing into array in createImageFromBlob (in case of i'mgnome). In my case it was like this:
export interface File {
...
original_name: name of file;
linkToPicture: string;
image: any;
}
...
files: File[] = [];//array for incoming data with link to pictures
this.getTable(...)
...
getTable(sendingQueryForm: QueryForm){
this.queryFormService.getTable(sendingQueryForm)
.subscribe(
(data) => {
this.files=data as File[];
for (let i = 0; i < this.files.length; i++) {
this.getImage('/api/auth/getFileImage/' + this.files[i].linkToPicture).subscribe(blob => {
this.createImageFromBlob(blob,i);
});
}
},
error => console.log(error)
);
}
getImage(imageUrl: string): Observable<Blob> {
return this.http.get(imageUrl, {responseType: 'blob'});
}
createImageFromBlob(image: Blob, index:number) {
const reader = new FileReader();
reader.addEventListener('load', () => {
this.files[index].image = reader.result;
}, false);
if (image) {
reader.readAsDataURL(image);
}
}
and in HTML:
<div *ngFor="let block of files; let i = index" >
<mat-card class="grid-card">
<div>
<img [src]="block.image" width=120>
<p>{{block.original_name}}</p>
</div>
</mat-card>
</div>
I hope it will useful for someone and thanks for topic!

Show country name on app

Im getting cordova notification on the console when I try to see my current country name on the browser.
There's something method or alternative to show me that on my tests.html, like in an input field (in the browser)?
On the other hand, if exist another alternative to show actual country name, please tell me.
tests.ts
import { Component, ViewChild, ElementRef } from "#angular/core";
import { NavController, IonicPage, NavParams } from "ionic-angular";
import {
NativeGeocoder,
NativeGeocoderReverseResult
} from "#ionic-native/native-geocoder";
import { Geolocation } from "#ionic-native/geolocation";
declare var google;
#IonicPage()
#Component({
selector: "page-tests",
templateUrl: "tests.html"
})
export class TestsPage {
#ViewChild("mapSmall") mapElement: ElementRef;
map: any;
message: any;
location: any;
gmLocation: { lat: number; lng: number } = { lat: 0, lng: 0 };
constructor(
public navCtrl: NavController,
private geolocation: Geolocation,
private nativeGeocoder: NativeGeocoder,
public navParams: NavParams,
) {
this.onLocateUser();
}
onLocateUser() {
this.geolocation
.getCurrentPosition()
.then(location => {
console.log(
"position gotten: long:",
location.coords.longitude,
" lat:",
location.coords.latitude
);
this.location = location;
this.gmLocation.lat = location.coords.latitude;
this.gmLocation.lng = location.coords.longitude;
this.nativeGeocoder.reverseGeocode(location.coords.latitude,location.coords.longitude)
.then((result: NativeGeocoderReverseResult) => console.log(JSON.stringify(result.countryName)))
.catch((error: any) => console.log(error));
})
.catch(error => {
console.log("Error getting location", error);
});
}
ionViewDidLoad() {
let latlng = new google.maps.LatLng(
this.gmLocation.lat,
this.gmLocation.lat
);
setTimeout(() => {
this.loadMap(latlng);
this.addMarker(this.gmLocation.lat, this.gmLocation.lng);
}, 100);
}
...
}

Data are not showing when two api called in` iondidenter`

I have one screen, which have two gridview . each grid view will populate some value after api calling. so my page will have 2 api calling. so when i call my api call method under constructor or ionViewDidEnter its not working. it allowing only one method to exeute.
here is my two api call method on one page .ts
Even i put under my constructor. But its not showing the data. so if i want to call the both api and need to display the data means how can i do that.please help me out. i was not able to find it out !!
Thanks in advance
updated:
import { Component, ViewChild } from '#angular/core';
import { AlertController, App, FabContainer, ItemSliding, List, ModalController, NavController, ToastController, LoadingController, Refresher } from 'ionic-angular';
import { CategoryDetailPage } from '../categorydetail/categorydetail';
import { ConferenceData } from '../../providers/conference-data';
import { UserData } from '../../providers/user-data';
import { SessionDetailPage } from '../session-detail/session-detail';
import { ScheduleFilterPage } from '../schedule-filter/schedule-filter';
import {Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
import { AuthService } from '../../providers/AuthService';
#Component({
selector: 'page-speaker-list',
templateUrl: 'speaker-list.html'
})
export class SpeakerListPage {
loading: any;
data: any;
Catdata: any;
Catdatanames: any;
resdata: any;
resCatdata: any;
resCatdatanames: any;
loginData: {username?: string} = {};
resloginData: {username?: string} = {};
constructor(
public alertCtrl: AlertController,
public app: App,
public loadingCtrl: LoadingController,
public modalCtrl: ModalController,
public navCtrl: NavController,
public toastCtrl: ToastController,
public confData: ConferenceData,
public user: UserData,
public http:Http,
public authService: AuthService
) {
}
ionViewDidEnter() {
this.show();
this.another();
}
show() {
this.showLoader();
this.authService.subs(this.loginData).then((result) => {
this.loading.dismiss();
this.data = result;
if(this.data.status == 1)
{
this.Catdata = this.data.SubjectList;
//this.Catdata.forEach(category => console.log(category.CatID));
for(let i=0; i<this.Catdata.length; i++) {
// console.log(this.Catdata[i].SubjectName);
}
}
else if(this.data.status == 0) {
let alert = this.alertCtrl.create({
title: 'Error',
subTitle: 'Please Enter Valid Username & Password',
buttons: ['OK']
});
alert.present();
}
}, (err) => {
this.loading.dismiss();
});
}
another() {
this.authService.allresources(this.resloginData).then((result) => {
this.resdata = result;
if(this.resdata.status == 1)
{
this.resCatdata = this.resdata.SubjectList;
for(let i=0; i<this.resCatdata.length; i++) {
// console.log(this.resCatdata[i].FileName);
}
}
else if(this.resdata.status == 0) {
let alert = this.alertCtrl.create({
title: 'Error',
subTitle: 'Please Enter Valid Username & Password',
buttons: ['OK']
});
alert.present();
}
}, (err) => {
});
}
showLoader(){
this.loading = this.loadingCtrl.create({
content: 'Authenticating...'
});
this.loading.present();
}
}

Use Google maps NodeJS geocode callback function results to draw map on AngularJS 2 component template

Hi all I am using the googles maps nodejs client web api and would like to display a map on my HTMLviews through AngularJS 2.
I have this server export that returns an object to my AngularJS2 client service
const googleMapsClient = require('#google/maps').createClient({
key: 'AIzaSyCYcyd0vCGRY6Pq5E0u_ECTFi4I9VmUE4o'
});
module.exports = (req, res) => {
googleMapsClient.geocode({
address: 'Cosmo City, Roodepoort USA street'
}, function(err,response) {
if(err) {
console.log("There was an error geocoding the address", err)
} else {
console.log("Here is the maps response", response.json.results)
var obj = {
name: "Thabo",
age: 23,
maps: response.json.results
};
res.json({obj});
}
});
}
The Angular2 services looks like this
#Injectable()
export class MyService {
constructor(private http: Http) { }
getMessage(): Promise<mma> {
return this.http.get('/map-moving-agents')
.toPromise()
.then((res)=> {
console.dir(res.json().maps);
return res.json().obj;
})
.catch(this.handleError);
}
Everything seems to be fine, I get the expected response from the server, now i would like to use this response to draw a map on my component template.
And then here is my AngularJS2 component
#Component({
moduleId:module.id,
selector: 'map-moving-agents',
templateUrl: 'moving-agents.html',
styleUrls: ['moving-agents.css'],
providers: [ MyService ]
})
export class MapMovingAgents implements OnInit{
msg : mma;
constructor(private myService: MyService ){}
getMessage(): void {
this.myService.getMessage().then((res) => {
this.msg = res;
console.log(this.msg.name);
})
}
ngOnInit(): void {
this.getMessage();
}
}
I have used the angular2-google-maps package, i now have this In my component class
export class MapMovingAgents implements OnInit{
map: any;
lat: number;
lng: number;
zoom: number = 18;
constructor(private myService: MyService ){}
getMessage(): void {
this.myService.getMessage().then((res) => {
this.map = res;
this.lat = this.map.maps[0].geometry.location.lat;
this.lng = this.map.maps[0].geometry.location.lng;
console.log(this.lat,this.lng);
})
}
And have this in my tempate
<sebm-google-map [latitude]="lat" [longitude]="lng" [zoom]="zoom">
<sebm-google-map-marker [latitude]="lat" [longitude]="lng"></sebm-google- map-marker>
</sebm-google-map>
I have also updated my app module by importing the module and passed it the api key
import { AgmCoreModule } from 'angular2-google-maps/core';
imports: [... AgmCoreModule.forRoot({
apiKey: 'AIzMSNPY'
})...]
You can read through the angular2-google-maps here